From ecfe31babb9240c2f8733b47cbdeb2fba023f76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kriv=C3=A1cs=20Schr=C3=B8der?= Date: Wed, 3 Oct 2018 10:10:56 +0200 Subject: [PATCH 1/5] Fix change log version comparison issue --- assets/js/qc-ext-qcExtraDirective.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/qc-ext-qcExtraDirective.js b/assets/js/qc-ext-qcExtraDirective.js index 4eb3245..a8ddbec 100644 --- a/assets/js/qc-ext-qcExtraDirective.js +++ b/assets/js/qc-ext-qcExtraDirective.js @@ -185,15 +185,15 @@ var qcExt; comicService.comic > constants.taglineThreshold) { self.missingDataInfo.push('a tagline'); } - + + var currentVersion = GM_info.script.version; if (qcExt.settings.version === undefined) { // Version is undefined. We're a new user! $log.debug('qcExtra(): Version undefined!'); self.showWelcomeMessage = true; } else if (qcExt.settings.version !== - self.currentVersion) { + currentVersion) { // Version is changed. Script has been updated! - $log.debug('qcExtra(): Version different!'); self.showUpdateMessage = true; } }); From 229a502373c5f4168b449d175a9e30cc6d014f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kriv=C3=A1cs=20Schr=C3=B8der?= Date: Sun, 7 Oct 2018 18:12:44 +0200 Subject: [PATCH 2/5] Upgraded the build system and script module system + more * Replaced JSHint and JSCS with ESLint * (Attempted to) Fix Travis build * Upgraded codebase to use ES6 modules instead of implied file order and allow using up to ES2017 features * Removed GM4 shim now that we're using native GM4 functions * Added upgrade path for settings saved with GM4 shim --- .eslintrc.js | 32 + .jscsrc | 152 -- .jshintrc | 31 - .travis.yml | 32 +- Gruntfile.js | 316 +-- README.md | 4 +- assets/js/app.js | 34 + assets/js/constants.js | 95 +- assets/js/dom-operations.js | 142 -- assets/js/gm4-shim.js | 61 - assets/js/module.decorateHttpService.js | 218 -- .../{bootstrap.js => modules/angular-app.js} | 13 +- assets/js/modules/angular/assemble.js | 82 + assets/js/{ => modules/angular}/config.js | 24 +- .../angular/controllers/bodyController.js} | 44 +- .../angular/controllers/comicController.js} | 14 +- .../angular/controllers/titleController.js} | 32 +- .../js/modules/angular/decorateHttpService.js | 210 ++ .../angular/directives/donutDirective.js} | 20 +- .../angular/directives/onErrorDirective.js} | 16 +- .../angular/directives/qcAddItemDirective.js} | 61 +- .../directives/qcChangeLogDirective.js} | 49 +- .../angular/directives/qcComicDirective.js} | 18 +- .../directives/qcComicNavDirective.js} | 25 +- .../angular/directives/qcDateDirective.js} | 36 +- .../directives/qcEditComicDataDirective.js} | 41 +- .../angular/directives/qcExtraDirective.js} | 75 +- .../directives/qcExtraNavDirective.js} | 14 +- .../directives/qcItemDetailsDirective.js} | 71 +- .../angular/directives/qcNavDirective.js} | 28 +- .../angular/directives/qcNewsDirective.js} | 26 +- .../angular/directives/qcRibbonDirective.js} | 32 +- .../directives/qcSetPublishDateDirective.js} | 29 +- .../directives/qcSetTaglineDirective.js} | 29 +- .../directives/qcSetTitleDirective.js} | 29 +- .../directives/qcSettingsDirective.js} | 41 +- .../js/{module.js => modules/angular/run.js} | 17 +- .../angular/services/colorService.js} | 40 +- .../angular/services/comicService.js} | 95 +- .../angular/services/eventFactory.js} | 20 +- .../services/messageReportingService.js} | 36 +- .../angular/services/styleService.js} | 44 +- assets/js/modules/dom-modifier.js | 143 ++ .../jQuery.changeElementType.js} | 0 assets/js/modules/settings.js | 105 + assets/js/qc-ext-compileTemplateDirective.js | 43 - assets/js/settings.js | 57 - assets/sass/style.scss | 6 +- assets/templates/variables.post.template | 2 +- assets/templates/variables.pre.template | 11 +- create-release.sh | 25 - licenseBanner.js | 38 + package-lock.json | 2055 +++++++++++------ package.json | 29 +- provision.sh | 2 - scripts/print-userscript-banner.js | 31 + userScriptBanner.js | 49 + 57 files changed, 2860 insertions(+), 2164 deletions(-) create mode 100644 .eslintrc.js delete mode 100644 .jscsrc delete mode 100644 .jshintrc create mode 100644 assets/js/app.js delete mode 100644 assets/js/dom-operations.js delete mode 100644 assets/js/gm4-shim.js delete mode 100644 assets/js/module.decorateHttpService.js rename assets/js/{bootstrap.js => modules/angular-app.js} (71%) create mode 100644 assets/js/modules/angular/assemble.js rename assets/js/{ => modules/angular}/config.js (67%) rename assets/js/{qc-ext-bodyController.js => modules/angular/controllers/bodyController.js} (73%) rename assets/js/{qc-ext-comicController.js => modules/angular/controllers/comicController.js} (76%) rename assets/js/{qc-ext-titleController.js => modules/angular/controllers/titleController.js} (74%) create mode 100644 assets/js/modules/angular/decorateHttpService.js rename assets/js/{qc-ext-donutDirective.js => modules/angular/directives/donutDirective.js} (85%) rename assets/js/{qc-ext-onErrorDirective.js => modules/angular/directives/onErrorDirective.js} (72%) rename assets/js/{qc-ext-qcAddItemDirective.js => modules/angular/directives/qcAddItemDirective.js} (84%) rename assets/js/{qc-ext-qcChangeLogDirective.js => modules/angular/directives/qcChangeLogDirective.js} (66%) rename assets/js/{qc-ext-qcComicDirective.js => modules/angular/directives/qcComicDirective.js} (72%) rename assets/js/{qc-ext-qcComicNavDirective.js => modules/angular/directives/qcComicNavDirective.js} (78%) rename assets/js/{qc-ext-qcDateDirective.js => modules/angular/directives/qcDateDirective.js} (76%) rename assets/js/{qc-ext-qcEditComicDataDirective.js => modules/angular/directives/qcEditComicDataDirective.js} (69%) rename assets/js/{qc-ext-qcExtraDirective.js => modules/angular/directives/qcExtraDirective.js} (83%) rename assets/js/{qc-ext-qcExtraNavDirective.js => modules/angular/directives/qcExtraNavDirective.js} (78%) rename assets/js/{qc-ext-qcItemDetailsDirective.js => modules/angular/directives/qcItemDetailsDirective.js} (81%) rename assets/js/{qc-ext-qcNavDirective.js => modules/angular/directives/qcNavDirective.js} (74%) rename assets/js/{qc-ext-qcNewsDirective.js => modules/angular/directives/qcNewsDirective.js} (83%) rename assets/js/{qc-ext-qcRibbonDirective.js => modules/angular/directives/qcRibbonDirective.js} (70%) rename assets/js/{qc-ext-qcSetPublishDateDirective.js => modules/angular/directives/qcSetPublishDateDirective.js} (79%) rename assets/js/{qc-ext-qcSetTaglineDirective.js => modules/angular/directives/qcSetTaglineDirective.js} (74%) rename assets/js/{qc-ext-qcSetTitleDirective.js => modules/angular/directives/qcSetTitleDirective.js} (74%) rename assets/js/{qc-ext-qcSettingsDirective.js => modules/angular/directives/qcSettingsDirective.js} (62%) rename assets/js/{module.js => modules/angular/run.js} (66%) rename assets/js/{qc-ext-colorService.js => modules/angular/services/colorService.js} (89%) rename assets/js/{qc-ext-comicService.js => modules/angular/services/comicService.js} (78%) rename assets/js/{qc-ext-eventFactory.js => modules/angular/services/eventFactory.js} (72%) rename assets/js/{qc-ext-messageReportingService.js => modules/angular/services/messageReportingService.js} (79%) rename assets/js/{qc-ext-styleService.js => modules/angular/services/styleService.js} (76%) create mode 100644 assets/js/modules/dom-modifier.js rename assets/js/{module.jQuery.changeElementType.js => modules/jQuery.changeElementType.js} (100%) create mode 100644 assets/js/modules/settings.js delete mode 100644 assets/js/qc-ext-compileTemplateDirective.js delete mode 100644 assets/js/settings.js delete mode 100755 create-release.sh create mode 100644 licenseBanner.js create mode 100644 scripts/print-userscript-banner.js create mode 100644 userScriptBanner.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..83c052d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,32 @@ +module.exports = { + "env": { + "browser": true, + "es6": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 2017, + "sourceType": "module" + }, + "rules": { + "indent": [ + "error", + "tab", + { "SwitchCase": 1 } + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + }, + "globals": { + "angular": true, + "jQuery": true, + "$": true, + "GM": true + } +}; \ No newline at end of file diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index d5cba18..0000000 --- a/.jscsrc +++ /dev/null @@ -1,152 +0,0 @@ -{ - "disallowDanglingUnderscores": true, - "disallowEmptyBlocks": true, - "disallowIdenticalDestructuringNames": true, - "disallowImplicitTypeConversion": [ - "numeric", - "boolean", - "binary", - "string" - ], - "disallowKeywordsOnNewLine": [ - "else" - ], - "disallowMixedSpacesAndTabs": "smart", - "disallowMultipleLineBreaks": true, - "disallowMultipleLineStrings": true, - "disallowMultipleSpaces": { - "allowEOLComments": true - }, - "disallowMultipleVarDecl": true, - "disallowNamedUnassignedFunctions": true, - "disallowNestedTernaries": true, - "disallowNewlineBeforeBlockStatements": true, - "disallowQuotedKeysInObjects": true, - "disallowSpaceAfterObjectKeys": true, - "disallowSpaceAfterPrefixUnaryOperators": true, - "disallowSpaceBeforeComma": true, - "disallowSpaceBeforePostfixUnaryOperators": true, - "disallowSpacesInAnonymousFunctionExpression": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInCallExpression": true, - "disallowSpacesInFunctionDeclaration": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInFunctionExpression": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInFunction": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInGenerator": { - "afterStar": true - }, - "disallowSpacesInNamedFunctionExpression": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInsideArrayBrackets": "all", - "disallowSpacesInsideBrackets": true, - "disallowSpacesInsideObjectBrackets": true, - "disallowSpacesInsideParentheses": true, - "disallowSpacesInsideParenthesizedExpression": true, - "disallowSpacesInsideTemplateStringPlaceholders": true, - "disallowTrailingComma": true, - "disallowTrailingWhitespace": "ignoreEmptyLines", - "disallowUnusedParams": true, - /*"jsDoc": { - "checkAnnotations": "jsdoc3", - "checkParamExistence": true, - "checkParamNames": true, - "requireParamTypes": true, - "checkRedundantParams": true, - "checkReturnTypes": true, - "checkRedundantReturns": true, - "requireReturnTypes": true, - "checkTypes": "strictNativeCase", - "checkRedundantAccess": "enforceLeadingUnderscore", - "leadingUnderscoreAccess": true, - "enforceExistence": true, - "requireNewlineAfterDescription": true, - "requireDescriptionCompleteSentence": true, - "requireParamDescription": true, - "requireReturnDescription": true - }, */ - /*"maximumLineLength": { - "value": 0, - "tabSize": 4, - "allExcept": [ - "regex" - ] - },*/ - "requireAlignedMultilineParams": 0, - "requireAnonymousFunctions": { - "allExcept": [ - "declarations" - ] - }, - "requireBlocksOnNewline": 1, - "requireCamelCaseOrUpperCaseIdentifiers": { - "allowedPrefixes": [ - "GM_" - ] - }, - "requireCapitalizedComments": true, - "requireCommaBeforeLineBreak": true, - "requireCurlyBraces": [ - "if", - "else", - "for", - "while", - "do", - "try", - "catch" - ], - "requireDotNotation": true, - "requireEarlyReturn": true, - "requireLineBreakAfterVariableAssignment": true, - "requireLineFeedAtFileEnd": true, - "requireNumericLiterals": true, - "requireObjectKeysOnNewLine": { - "allExcept": ["sameLine"] - }, - "requireOperatorBeforeLineBreak": true, - "requirePaddingNewLinesAfterUseStrict": true, - "requireParenthesesAroundIIFE": true, - "requireSemicolons": true, - "requireSpaceAfterBinaryOperators": true, - "requireSpaceAfterComma": true, - "requireSpaceAfterLineComment": true, - "requireSpaceBeforeBinaryOperators": true, - "requireSpaceBeforeBlockStatements": true, - "requireSpaceBeforeKeywords": [ - "else", - "while", - "catch", - "finally" - ], - "requireSpaceBeforeObjectValues": true, - "requireSpaceBetweenArguments": true, - "requireSpacesInConditionalExpression": true, - "requireSpacesInForStatement": true, - "requireSpacesInFunctionDeclaration": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunction": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInGenerator": { - "beforeStar": true - }, - "requireSpacesInNamedFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "safeContextKeyword": ["self"], - "validateIndentation": "\t", - "validateLineBreaks": null, - "validateParameterSeparator": ", ", - "validateQuoteMarks": "'" -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index f24af91..0000000 --- a/.jshintrc +++ /dev/null @@ -1,31 +0,0 @@ -{ - "bitwise": true, - "curly": true, - "eqeqeq": true, - "forin": true, - "freeze": true, - "futurehostile": true, - "globals": { - "angular": true, - "GM_info": true, - "GM_xmlhttpRequest": true, - "GM_getValue": true, - "GM_setValue": true, - "unsafeWindow": true, - "GM": true - }, - "latedef": true, - "nocomma": true, - "nonbsp": true, - "nonew": true, - "notypeof": true, - "quotmark": "single", - "shadow": "outer", - "singleGroups": true, - "strict": true, - "undef": true, - "unused": true, - - "browser": true, - "jquery": true -} diff --git a/.travis.yml b/.travis.yml index 53b5036..55df980 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,26 @@ language: node_js node_js: - - "4.7.0" -before_install: - - npm install -g grunt-cli - - rvm install 2.4.1 - - gem install sass --version "=3.4.23" - - gem install compass --version "=1.0.3" +- 8.4.0 +before_install: +- npm install -g grunt-cli +- rvm install 2.4.2 +- gem install sass --version "=3.4.25" +- gem install compass --version "=1.0.3" install: - - npm update -g - - npm install -script: grunt build +- npm update -g +- npm install +script: +- grunt build +- npm run print-userscript-banner +deploy: + provider: releases + api_key: + secure: UfVMZo8geJjIw3p9p2Iw5LDXWXVcJKNBkAam8PDDWlqprPhRuHsvvvev5BGchjZ8mlr/3R2poYn+6KXWqiGNh/1/4vEx1GCeo9/Y7IdZw4Zk11Z0rZIsg0G8VyQidLwEJC/g3y5INV3RkHmg2ux5qHpgWXVaaVInyPgHEYxoVeYtGb1QRQfu45axLjxhT6PbGjSzQ9oa6kE5+mR+GZAfr4KdiVXYVfN+VFF75KMh8swoRUOtxX5ED+mblC83ar25BHUCSwDvkfMZgNJHziTI0KzIJHSoxAZnso14cx6/BWcRW3chsU/Eh5mXT3Z94iGIgrTTNKjq6nDC/HJuRMwVKfMGSkQBOpAtKEGpSusLOsluOw1XVRytnkIXEE5+CnQNS8J0GqKUU9Ea47EScH+VW4xUmWolyGDuYjZC0tH2GFhxcAXDUFMbCxTwVNIuoph7nokxbYAPgGc4g0WeI/fNJ0szHTw9mGFbWXFh4kWj0bCEcKwPBkgrN18n7l1EiM7uR221jUPjqJihS5hiyVyBsjzxefS/lY1+9C0Fb0tBRMWE/jEqgh1LVA5ir8LiRlV3FxHdT04ebR6y5aq5e1A8Xfu+z72aPi8ZmGz4hdU4VHIou6VzzzGuPp9lnQx5UEZ+nvBAPeoprcXG0HV9CwaJa3aStPdSm8WSJxNHdyMUQdQ= + file: + - dist/qc-ext.min.user.js + - dist/qc-ext.user.js + - dist/qc-ext.meta.js + skip_cleanup: true + on: + repo: Questionable-Content-Extensions/client + tags: true diff --git a/Gruntfile.js b/Gruntfile.js index 7813203..cd9ce6b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,163 +17,167 @@ /* global module, require */ +let resolve = require('rollup-plugin-node-resolve'); +let commonJs = require('rollup-plugin-commonjs'); + +let licenseBanner = require('./licenseBanner'); +let userScriptBanner = require('./userScriptBanner'); + +let baseFileName = 'qc-ext'; + module.exports = function (grunt) { - 'use strict'; + 'use strict'; - // Project configuration. - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - watch: { - css: { - files: [ - '**/*.sass', - '**/*.scss' - ], - tasks: ['build'] - }, - js: { - files: [ - 'assets/js/*.js', - 'Gruntfile.js' - ], - tasks: ['build'] - }, - templates: { - files: [ - 'templates/*.*' - ], - tasks: ['build'] - } - }, - compass: { - dist: { - options: { - sassDir: 'assets/sass', - cssDir: 'assets/generated', - outputStyle: 'compressed' - } - } - }, - jshint: { - options: { - jshintrc: '.jshintrc', - verbose: true - }, - all: ['Gruntfile.js', 'assets/js/*.js'] - }, - jscs: { - src: 'assets/js/*.js', - options: { - config: '.jscsrc', - fix: false - } - }, - concat: { - options: { - separator: '', - stripBanners: true - }, - variables: { - src: [ - 'assets/generated/css.variables.pass1.js', - 'assets/generated/angular.variables.pass1.js', - 'assets/templates/variables.post.template' - ], - dest: 'assets/generated/variables.pass2.js' - }, - source: { - options: { - banner: '<%= pkg.licenseBanner %>\n<%= pkg.userscriptBanner %>' - }, - src: [ - 'assets/js/gm4-shim.js', - 'assets/js/constants.js', - 'assets/generated/variables.pass2.js', - 'assets/js/settings.js', - 'assets/js/module.js', - 'assets/js/module.*.js', - 'assets/js/dom-operations.js', - 'assets/js/config.js', - 'assets/js/qc-ext-*.js', - 'assets/js/bootstrap.js' - ], - dest: 'dist/qc-ext.user.js' - } - }, - uglify: { - options: { - mangle: { - except: ['jQuery', 'angular', 'GM_setValue', 'GM_getValue', 'GM_deleteValue', 'GM_xmlhttprequest', 'unsafeWindow'], - screwIE8: true - }, - banner: '<%= pkg.licenseBanner %>\n<%= pkg.userscriptBanner %>' - }, - target: { - files: { - 'dist/qc-ext.min.user.js': ['dist/qc-ext.user.js'] - } - } - }, - filesToJavascript: { - css: { - options: { - inputFilesFolder: 'assets/generated', - inputFileExtension: 'css', - outputBaseFile: 'assets/templates/variables.pre.template', - outputBaseFileVariable: 'qcExt.variables.css', - outputFile: 'assets/generated/css.variables.pass1.js' - } - }, - angularTemplates: { - options: { - inputFilesFolder: 'assets/generated', - inputFileExtension: 'html', - outputBaseFile: 'assets/templates/variables.empty.template', - outputBaseFileVariable: 'qcExt.variables.angularTemplates', - outputFile: 'assets/generated/angular.variables.pass1.js' - } - } - }, - htmlmin: { - dist: { - options: { - removeComments: true, - collapseWhitespace: true - }, - files: { - 'assets/generated/navigation.html': 'assets/templates/navigation.html', - 'assets/generated/extra.html': 'assets/templates/extra.html', - 'assets/generated/extraNav.html': 'assets/templates/extraNav.html', - 'assets/generated/settings.html': 'assets/templates/settings.html', - 'assets/generated/editComicData.html': 'assets/templates/editComicData.html', - 'assets/generated/addItem.html': 'assets/templates/addItem.html', - 'assets/generated/setTitle.html': 'assets/templates/setTitle.html', - 'assets/generated/setTagline.html': 'assets/templates/setTagline.html', - 'assets/generated/setPublishDate.html': 'assets/templates/setPublishDate.html', - 'assets/generated/donut.html': 'assets/templates/donut.html', - 'assets/generated/ribbon.html': 'assets/templates/ribbon.html', - 'assets/generated/itemDetails.html': 'assets/templates/itemDetails.html', - 'assets/generated/comicNav.html': 'assets/templates/comicNav.html', - 'assets/generated/changeLog.html': 'assets/templates/changeLog.html', - 'assets/generated/date.html': 'assets/templates/date.html' - } - } - } - }); + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + watch: { + css: { + files: [ + '**/*.sass', + '**/*.scss' + ], + tasks: ['build'] + }, + js: { + files: [ + 'assets/js/**/*.js', + 'Gruntfile.js' + ], + tasks: ['build'] + }, + templates: { + files: [ + 'templates/*.*' + ], + tasks: ['build'] + } + }, + compass: { + dist: { + options: { + sassDir: 'assets/sass', + cssDir: 'assets/generated', + outputStyle: 'compressed' + } + } + }, + eslint: { + target: [ + 'assets/js/**/*.js', + '*.js', + 'scripts/*.js' + ] + }, + concat: { + options: { + separator: '', + stripBanners: true + }, + variables: { + src: [ + 'assets/templates/variables.pre.template', + 'assets/generated/css.variables.pass1.js', + 'assets/generated/html.variables.pass1.js', + 'assets/templates/variables.post.template' + ], + dest: 'assets/generated/variables.pass2.js' + }, + source: { + options: { + banner: `${licenseBanner}\n${userScriptBanner}\n` + }, + src: [ + 'assets/generated/rollup.js' + ], + dest: `dist/${baseFileName}.user.js` + } + }, + uglify: { + options: { + banner: licenseBanner + '\n' + userScriptBanner + }, + target: { + files: { + [`dist/${baseFileName}.min.user.js`]: [`dist/${baseFileName}.user.js`] + } + } + }, + filesToJavascript: { + css: { + options: { + inputFilesFolder: 'assets/generated', + inputFileExtension: 'css', + outputBaseFile: 'assets/templates/variables.empty.template', + outputBaseFileVariable: 'variables.css', + outputFile: 'assets/generated/css.variables.pass1.js' + } + }, + htmlTemplates: { + options: { + inputFilesFolder: 'assets/generated', + inputFileExtension: 'html', + outputBaseFile: 'assets/templates/variables.empty.template', + outputBaseFileVariable: 'variables.html', + outputFile: 'assets/generated/html.variables.pass1.js' + } + } + }, + htmlmin: { + dist: { + options: { + removeComments: true, + collapseWhitespace: true + }, + files: { + 'assets/generated/navigation.html': 'assets/templates/navigation.html', + 'assets/generated/extra.html': 'assets/templates/extra.html', + 'assets/generated/extraNav.html': 'assets/templates/extraNav.html', + 'assets/generated/settings.html': 'assets/templates/settings.html', + 'assets/generated/editComicData.html': 'assets/templates/editComicData.html', + 'assets/generated/addItem.html': 'assets/templates/addItem.html', + 'assets/generated/setTitle.html': 'assets/templates/setTitle.html', + 'assets/generated/setTagline.html': 'assets/templates/setTagline.html', + 'assets/generated/setPublishDate.html': 'assets/templates/setPublishDate.html', + 'assets/generated/donut.html': 'assets/templates/donut.html', + 'assets/generated/ribbon.html': 'assets/templates/ribbon.html', + 'assets/generated/itemDetails.html': 'assets/templates/itemDetails.html', + 'assets/generated/comicNav.html': 'assets/templates/comicNav.html', + 'assets/generated/changeLog.html': 'assets/templates/changeLog.html', + 'assets/generated/date.html': 'assets/templates/date.html' + } + } + }, + rollup: { + options: { + plugins: [ + resolve({ + browser: true + }), + commonJs() + ] + }, + main: { + files: { + 'assets/generated/rollup.js': 'assets/js/app.js' + } + } + } + }); - // Load the Grunt tasks. - require('load-grunt-tasks')(grunt); + // Load the Grunt tasks. + require('load-grunt-tasks')(grunt); - // Register the tasks. - grunt.registerTask('default', ['build']); - grunt.registerTask('build', [ - 'jshint', // Check for lint - 'jscs', // Check code style - 'compass', // Compile CSS - 'htmlmin', // Minify HTML templates - 'filesToJavascript', // Convert HTML templates to JS variables - 'concat:variables', // Create finished variable.pass2.js file - 'concat:source', // Concatenate all the javascript files into one - 'uglify', // Minify the javascript - ]); + // Register the tasks. + grunt.registerTask('default', ['build']); + grunt.registerTask('build', [ + 'eslint', // Check for lint + 'compass', // Compile CSS + 'htmlmin', // Minify HTML templates + 'filesToJavascript', // Convert HTML templates to JS variables + 'concat:variables', // Create finished variable.pass2.js file + 'rollup:main', // Rollup all the javascript files into one + 'concat:source', // Add banner to rollup result + 'uglify', // Minify the javascript + ]); }; diff --git a/README.md b/README.md index 82a3861..dfeefea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Questionable Content Extensions User Script [![Build Status](https://travis-ci.org/Questionable-Content-Extensions/client.svg?branch=master)](https://travis-ci.org/Questionable-Content-Extensions/client) [![Dependency Status](https://www.versioneye.com/user/projects/58da3f4f26a5bb0038e42095/badge.svg?style=flat)](https://www.versioneye.com/user/projects/58da3f4f26a5bb0038e42095) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com/) +# Questionable Content Extensions User Script [![Build Status](https://travis-ci.org/Questionable-Content-Extensions/client.svg?branch=master)](https://travis-ci.org/Questionable-Content-Extensions/client) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com/) ## Getting Started @@ -29,8 +29,6 @@ This project requires [Node.js®](https://nodejs.org/) and [Ruby](https://www.ru ```shell gem install compass # If you don't have compass installed already npm install -g grunt-cli # If you don't have grunt installed already -npm install -g jsonlint # If you don't have jsonlint installed already -npm install -g jshint # If you don't have jshint installed already npm install # To install all the grunt plugins we use grunt build # To build our script ``` diff --git a/assets/js/app.js b/assets/js/app.js new file mode 100644 index 0000000..c539d9a --- /dev/null +++ b/assets/js/app.js @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016-2018 Alexander Krivács Schrøder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import './modules/jQuery.changeElementType'; + +import settings from './modules/settings'; +import DomModifier from './modules/dom-modifier'; +import { setup as setupAngular } from './modules/angular-app'; + +(async () => { + await settings.loadSettings(); + + let domModifier = new DomModifier(); + domModifier.modify(); + + setupAngular(); + + // Let's go! + angular.bootstrap($('html').get(0), ['qc-spa']); +})(); diff --git a/assets/js/constants.js b/assets/js/constants.js index 14b95aa..a6eb987 100644 --- a/assets/js/constants.js +++ b/assets/js/constants.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,56 +15,69 @@ * along with this program. If not, see . */ -var constants; +// Set this to true when working against your local test server. +// NEVER CHECK THIS FILE IN WITH developmentMode = true! +const developmentMode = false; -(function(constants) { - 'use strict'; - - constants.settingsKey = 'settings'; - - // Comics after 3132 should have a tagline - constants.taglineThreshold = 3132; +function getBaseUrl() { + if (developmentMode) { + return 'http://localhost/questionablecontentextensions/web/'; + } else { + return 'https://questionablextensions.net/'; + } +} - // Set this to true when working against your local test server. - // NEVER CHECK THIS FILE IN WITH developmentMode = true! - constants.developmentMode = false; - if (constants.developmentMode) { - constants.baseUrl = - 'http://localhost/questionablecontentextensions/web/'; - constants.webServiceBaseUrl = constants.baseUrl + 'app_dev.php/'; +function getWebserviceBaseUrl() { + if (developmentMode) { + return getBaseUrl() + 'app_dev.php/'; } else { - constants.baseUrl = 'https://questionablextensions.net/'; - constants.webServiceBaseUrl = constants.baseUrl; + return getBaseUrl(); } +} + +const comicDataUrl = getWebserviceBaseUrl() + 'comicdata/'; +const itemDataUrl = getWebserviceBaseUrl() + 'itemdata/'; - constants.comicDataUrl = constants.webServiceBaseUrl + 'comicdata/'; - constants.addItemToComicUrl = constants.comicDataUrl + 'additem'; - constants.removeItemFromComicUrl = constants.comicDataUrl + 'removeitem'; - constants.setComicTitleUrl = constants.comicDataUrl + 'settitle'; - constants.setComicTaglineUrl = constants.comicDataUrl + 'settagline'; - constants.setPublishDateUrl = constants.comicDataUrl + 'setpublishdate'; - constants.setGuestComicUrl = constants.comicDataUrl + 'setguest'; - constants.setNonCanonUrl = constants.comicDataUrl + 'setnoncanon'; +let constants = { + settingsKey: 'settings', + + developmentMode, + baseUrl: getBaseUrl(), + comicDataUrl, + itemDataUrl, + + // Comics after 3132 should have a tagline + taglineThreshold: 3132, + + addItemToComicUrl: comicDataUrl + 'additem', + removeItemFromComicUrl: comicDataUrl + 'removeitem', + setComicTitleUrl: comicDataUrl + 'settitle', + setComicTaglineUrl: comicDataUrl + 'settagline', + setPublishDateUrl: comicDataUrl + 'setpublishdate', + setGuestComicUrl: comicDataUrl + 'setguest', + setNonCanonUrl: comicDataUrl + 'setnoncanon', - constants.itemDataUrl = constants.webServiceBaseUrl + 'itemdata/'; - constants.itemFriendDataUrl = constants.itemDataUrl + 'friends/'; - constants.itemLocationDataUrl = constants.itemDataUrl + 'locations/'; - constants.setItemDataPropertyUrl = constants.itemDataUrl + 'setproperty'; - constants.characterImageBaseUrl = constants.baseUrl + 'images/characters/'; - constants.characterImageExtension = 'png'; + itemFriendDataUrl: itemDataUrl + 'friends/', + itemLocationDataUrl: itemDataUrl + 'locations/', + setItemDataPropertyUrl: itemDataUrl + 'setproperty', + + characterImageBaseUrl: getBaseUrl() + 'images/characters/', + characterImageExtension: 'png', - constants.comicExtensions = ['png', 'gif', 'jpg']; + comicExtensions: ['png', 'gif', 'jpg'], - constants.comicdataLoadingEvent = 'comicdata-loading'; - constants.comicdataLoadedEvent = 'comicdata-loaded'; - constants.comicdataErrorEvent = 'comicdata-error'; - constants.itemsChangedEvent = 'items-changed'; - - constants.messages = { + comicdataLoadingEvent: 'comicdata-loading', + comicdataLoadedEvent: 'comicdata-loaded', + comicdataErrorEvent: 'comicdata-error', + itemsChangedEvent: 'items-changed', + + messages: { maintenance: 'The Questionable Extensions' + ' server is currently undergoing maintenance.' + ' Normal operation should resume within a' + ' few minutes.' - }; -})(constants || (constants = {})); + } +}; + +export default constants; diff --git a/assets/js/dom-operations.js b/assets/js/dom-operations.js deleted file mode 100644 index f552f7b..0000000 --- a/assets/js/dom-operations.js +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* global constants, console */ - -var qcExt; - -(function(qcExt) { - 'use strict'; - - // Add our modal windows - $('body').prepend(''); - $('body').prepend(''); - $('body').prepend(''); - $('body').prepend(''); - - // Take control over the page's title - $('title').replaceWith('' + - '{{t.title}}'); - - /** - * Adds a CSS element to the of the document. - * - * @param {string} href - URL to the CSS document - */ - function addCss(href) { - $('head').prepend( - '' - ); - } - - /** - * Adds an inline CSS ')); - } - - // Bootstrap - addCss(constants.baseUrl + 'style/bootstrap.min.css'); - - // Font Awesome - addCss('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/' + - 'font-awesome.min.css'); - - // Style adder function - addStyle(qcExt.variables.css.style); - - // Take over the comic link - // For some reason, Jeph didn't use id="strip" on the comic on - // the front page. Whyyy???? - // (In other words, we have to use this method instead of just '#strip'.) - var comicImg = $('img[src*="/comics/"]'); - var comicAnchor = comicImg.parent('a'); - - if (comicAnchor.length !== 1) { - comicImg.wrap($('')); - comicAnchor = comicImg.parent('a'); - } - - $('body').append($('
')); - - // To avoid triggering a flash of the comic "reloading", do in-place DOM - // manipulation instead of replacing the whole thing with a template. - // Fixes issue #13 - var comicDirective = $(''); - comicAnchor.before(comicDirective); - comicAnchor.detach().appendTo(comicDirective); - comicAnchor.attr('ng-href', 'view.php?comic={{c.comicService.nextComic}}'); - comicImg.attr('ng-src', 'http://questionablecontent.net/comics/' + - '{{c.comicService.comic}}.{{c.comicService.comicExtension}}'); - comicImg.attr('ng-click', 'c.next($event)'); - comicImg.attr('on-error', 'c.comicService.canFallback() ' + - '&& c.comicService.tryFallback()'); - - // #comicDirective.attr('id', 'comic-anchor'); - comicDirective.append($('')); - - var comicImage = comicImg.get(0); - var comicLinkUrl = comicImage.src; - - comicLinkUrl = comicLinkUrl.split('/'); - var comic = parseInt(comicLinkUrl[comicLinkUrl.length - 1].split('.')[0]); - - qcExt.app.constant('startComic', comic); - - // Figure out what the latest comic # is based on the URL in the - // "Latest/Last" navigation button. - var latestUrl = $('#comicnav a').get(3).href; - var latestComic = parseInt(latestUrl.split('=')[1]); - if (isNaN(latestComic)) { - latestComic = comic; - } - - if (qcExt.settings.showDebugLogs) { - console.debug('Running QC Extensions v' + GM_info.script.version); - console.debug('Latest URL:', latestUrl, 'Latest Comic:', latestComic); - } - - qcExt.app.constant('latestComic', latestComic); - - $('body #comicnav') - .replaceWith(''); - - if ($('#news, #newspost').prev().prop('tagName') === 'QC-NAV') { - // There's no date section: Insert our own - $('#news, #newspost').before(''); - } else { - // There's a date section: Replace with our own - $('#news, #newspost').prev().replaceWith(''); - } - - $('#news, #newspost').replaceWith(''); - - comicDirective.parent().siblings('.small-2').prepend(''); - - // Set a base (required by Angular's html5Mode) - $('head').append(''); - - // Set up ng-controller for - $('body').attr('ng-controller', 'bodyController as b'); - - // Fixed positioned element covering the whole page used to show messages - // See the messageReportingService for details. - $('body').append('
'); -})(qcExt || (qcExt = {})); diff --git a/assets/js/gm4-shim.js b/assets/js/gm4-shim.js deleted file mode 100644 index 9226e0d..0000000 --- a/assets/js/gm4-shim.js +++ /dev/null @@ -1,61 +0,0 @@ -/* -Functions copied from https://gist.github.com/arantius/3123124 -The MIT License (MIT) - -Copyright (c) 2014 Anthony Lieuallen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. -*/ - -/*jshint unused:false, esversion: 6, latedef: false*/ - -if (typeof GM !== 'undefined' && typeof GM_getValue === 'undefined') { - if (typeof GM_info === 'undefined') { const GM_info = GM.info; } - var GM_xmlhttpRequest = GM.xmlHttpRequest; - var storagePrefix = GM.info.script.name.replace(/[^A-Z]*/g, '') + '-'; - - // The following functions all use local storage, and thus could be accessed - // by the host. They are also restricted to a single domain. - - var GM_deleteValue = function(aKey) { - 'use strict'; - - localStorage.removeItem(storagePrefix + aKey); - }; - - var GM_getValue = function(aKey, aDefault) { - 'use strict'; - - var aValue = localStorage.getItem(storagePrefix + aKey); - if (null === aValue && 'undefined' !== typeof aDefault) { return aDefault; } - return aValue; - }; - - var GM_listValues = function() { - 'use strict'; - - var prefixLen = storagePrefix.length; - var values = []; - for (var i = 0; i < localStorage.length; i++) { - var k = localStorage.key(i); - if (k.substr(0, prefixLen) === storagePrefix) { - values.push(k.substr(prefixLen)); - } - } - return values; - }; - - var GM_setValue = function(aKey, aVal) { - 'use strict'; - - localStorage.setItem(storagePrefix + aKey, aVal); - }; -} diff --git a/assets/js/module.decorateHttpService.js b/assets/js/module.decorateHttpService.js deleted file mode 100644 index e8fcc0f..0000000 --- a/assets/js/module.decorateHttpService.js +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2016 Alexander Krivács Schrøder - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -var qcExt; - -(function(qcExt) { - 'use strict'; - - (function(modules) { - // TODO: Since we're not using the original service at all, we might - // as well completely replace it rather than decorate it... - // http://www.bennadel.com/blog/ - // 2927-overriding-core-and-custom-services-in-angularjs.htm - modules.decorateHttpService = function($provide) { - - // Let's take over $http and make it use Greasemonkey's cross-domain - // XMLHTTPRequests instead of the browser's. - $provide.decorator('$http', function() { - - // START Code bits borrowed from angular - // (see angular's license for details) - var APPLICATION_JSON = 'application/json'; - var JSON_START = /^\[|^\{(?!\{)/; - var JSON_ENDS = { - '[': /]$/, - '{': /}$/ - }; - var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; - - function isJsonLike(str) { - var jsonStart = str.match(JSON_START); - - return jsonStart && JSON_ENDS[jsonStart[0]].test(str); - } - - function isString(value) { - return typeof value === 'string'; - } - - function fromJson(json) { - return isString(json) ? JSON.parse(json) : json; - } - - function defaultHttpResponseTransform(data, headers) { - if (!isString(data)) { - return data; - } - - // Strip json vulnerability protection prefix - // and trim whitespace - var tempData = data.replace(JSON_PROTECTION_PREFIX, '') - .trim(); - - if (!tempData) { - return data; - } - - var contentType = headers('Content-Type'); - - if (contentType && - contentType.indexOf(APPLICATION_JSON) === 0 || - isJsonLike(tempData)) { - data = fromJson(tempData); - } - - return data; - } - - // END Code bits borrowed from angular - - function getHeaderFunction(headers) { - var keyedHeaders = {}; - - angular.forEach(headers, function(value) { - var splitValue = value.trim().split(':', 2); - - if (splitValue.length < 2) { - return; - } - - keyedHeaders[splitValue[0].trim()] = - splitValue[1].trim(); - }); - - return function(key) { - return keyedHeaders[key] || null; - }; - } - - var injector = angular.injector(['ng']); - var $q = injector.get('$q'); - var ourHttp = { - get: function(url, config) { - return $q(function(resolve, reject) { - GM_xmlhttpRequest({ - method: 'GET', - url: url, - headers: { - Accept: APPLICATION_JSON - }, - onload: function(gmResponse) { - var headers = getHeaderFunction( - gmResponse.responseHeaders - .split('\n')); - var responseData = gmResponse.response; - - responseData = defaultHttpResponseTransform( - responseData, headers); - var response = { - data: responseData, - status: gmResponse.status, - headers: headers, - config: config, - statusText: gmResponse.statusText - }; - - resolve(response); - }, - onerror: function(gmResponse) { - var headers = getHeaderFunction(gmResponse - .responseHeaders.split('\n')); - var responseData = gmResponse.response; - - responseData = defaultHttpResponseTransform( - responseData, headers); - var response = { - data: responseData, - status: gmResponse.status, - headers: headers, - config: config, - statusText: gmResponse.statusText - }; - - reject(response); - } - }); - }); - }, - post: function(url, data, config) { - return $q(function(resolve, reject) { - GM_xmlhttpRequest({ - method: 'POST', - url: url, - data: JSON.stringify(data), - headers: { - 'Content-Type': APPLICATION_JSON, - Accept: APPLICATION_JSON - }, - onload: function(gmResponse) { - var headers = getHeaderFunction( - gmResponse.responseHeaders - .split('\n')); - var responseData = gmResponse.response; - - responseData = defaultHttpResponseTransform( - responseData, headers); - var response = { - data: responseData, - status: gmResponse.status, - headers: headers, - config: config, - statusText: gmResponse.statusText - }; - - resolve(response); - }, - onerror: function(gmResponse) { - var headers = getHeaderFunction(gmResponse - .responseHeaders.split('\n')); - var responseData = gmResponse.response; - - responseData = defaultHttpResponseTransform( - responseData, headers); - var response = { - data: responseData, - status: gmResponse.status, - headers: headers, - config: config, - statusText: gmResponse.statusText - }; - - reject(response); - } - }); - }); - } - }; - - /* Methods/properties to implement for full compatibility: - * pendingRequests - * delete - * head - * jsonp - * post - * put - * patch - * defaults - */ - - return ourHttp; - }); - }; - })(qcExt.modules || (qcExt.modules = {})); -})(qcExt || (qcExt = {})); diff --git a/assets/js/bootstrap.js b/assets/js/modules/angular-app.js similarity index 71% rename from assets/js/bootstrap.js rename to assets/js/modules/angular-app.js index e44e6ac..3c2c72b 100644 --- a/assets/js/bootstrap.js +++ b/assets/js/modules/angular-app.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,8 +15,11 @@ * along with this program. If not, see . */ -(function() { - 'use strict'; +import assemble from './angular/assemble'; - angular.bootstrap($('html').get(0), ['qc-spa']); -})(); +const angularApp = angular.module('qc-spa', ['ui.router']); +export function setup() { + assemble(angularApp); +} + +export default angularApp; diff --git a/assets/js/modules/angular/assemble.js b/assets/js/modules/angular/assemble.js new file mode 100644 index 0000000..9f2e057 --- /dev/null +++ b/assets/js/modules/angular/assemble.js @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016-2018 Alexander Krivács Schrøder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import config from './config'; +import run from './run'; + +import bodyController from './controllers/bodyController'; +import comicController from './controllers/comicController'; +import titleController from './controllers/titleController'; + +import colorService from './services/colorService'; +import comicService from './services/comicService'; +import eventFactory from './services/eventFactory'; +import messageReportingService from './services/messageReportingService'; +import styleService from './services/styleService'; + +import donutDirective from './directives/donutDirective'; +import onErrorDirective from './directives/onErrorDirective'; +import qcAddItemDirective from './directives/qcAddItemDirective'; +import qcChangeLogDirective from './directives/qcChangeLogDirective'; +import qcComicDirective from './directives/qcComicDirective'; +import qcComicNavDirective from './directives/qcComicNavDirective'; +import qcDateDirective from './directives/qcDateDirective'; +import qcEditComicDataDirective from './directives/qcEditComicDataDirective'; +import qcExtraDirective from './directives/qcExtraDirective'; +import qcExtraNavDirective from './directives/qcExtraNavDirective'; +import qcItemDetailsDirective from './directives/qcItemDetailsDirective'; +import qcNavDirective from './directives/qcNavDirective'; +import qcNewsDirective from './directives/qcNewsDirective'; +import qcRibbonDirective from './directives/qcRibbonDirective'; +import qcSetPublishDateDirective from './directives/qcSetPublishDateDirective'; +import qcSetTaglineDirective from './directives/qcSetTaglineDirective'; +import qcSettingsDirective from './directives/qcSettingsDirective'; +import qcSetTitleDirective from './directives/qcSetTitleDirective'; + +export default function (app) { + config(app); + run(app); + + bodyController(app); + comicController(app); + titleController(app); + + colorService(app); + comicService(app); + eventFactory(app); + messageReportingService(app); + styleService(app); + + donutDirective(app); + onErrorDirective(app); + qcAddItemDirective(app); + qcChangeLogDirective(app); + qcComicDirective(app); + qcComicNavDirective(app); + qcDateDirective(app); + qcEditComicDataDirective(app); + qcExtraDirective(app); + qcExtraNavDirective(app); + qcItemDetailsDirective(app); + qcNavDirective(app); + qcNewsDirective(app); + qcRibbonDirective(app); + qcSetPublishDateDirective(app); + qcSetTaglineDirective(app); + qcSettingsDirective(app); + qcSetTitleDirective(app); +} diff --git a/assets/js/config.js b/assets/js/modules/angular/config.js similarity index 67% rename from assets/js/config.js rename to assets/js/modules/angular/config.js index dcd6e09..b378271 100644 --- a/assets/js/config.js +++ b/assets/js/modules/angular/config.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,20 +15,20 @@ * along with this program. If not, see . */ -var qcExt; +import settings from './../settings'; -(function(qcExt) { - 'use strict'; +import decorateHttpService from './decorateHttpService'; +export default function (app) { // Set up routing and do other configuration - qcExt.app.config(['$stateProvider', '$urlRouterProvider', + app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', '$provide', '$logProvider', - function($stateProvider, $urlRouterProvider, $locationProvider, + function ($stateProvider, $urlRouterProvider, $locationProvider, $provide, $logProvider) { - qcExt.modules.decorateHttpService($provide); + decorateHttpService($provide); $stateProvider.state('homepage', { - url: '^/', + url: '^/$', controller: 'comicController', controllerAs: 'c', template: '
' @@ -38,12 +38,12 @@ var qcExt; controllerAs: 'c', template: '
' }); - $urlRouterProvider.otherwise(function() { - window.location.reload(); + $urlRouterProvider.otherwise(function ($injector, $location) { + GM.openInTab($location.$$absUrl, false); }); $locationProvider.html5Mode(true); - $logProvider.debugEnabled(qcExt.settings.showDebugLogs); + $logProvider.debugEnabled(settings.showDebugLogs); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-bodyController.js b/assets/js/modules/angular/controllers/bodyController.js similarity index 73% rename from assets/js/qc-ext-bodyController.js rename to assets/js/modules/angular/controllers/bodyController.js index 523992f..bd8ba5f 100644 --- a/assets/js/qc-ext-bodyController.js +++ b/assets/js/modules/angular/controllers/bodyController.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,56 +15,50 @@ * along with this program. If not, see . */ -var qcExt; +import settings from '../../settings'; -(function(qcExt) { - 'use strict'; - - qcExt.app.controller('bodyController', ['$log', '$scope', 'comicService', - function($log, $scope, comicService) { +export default function (app) { + app.controller('bodyController', ['$log', '$scope', 'comicService', + function ($log, $scope, comicService) { $log.debug('START bodyController()'); var isStupidFox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; function previous() { - $scope.$apply(function() { + $scope.$apply(function () { comicService.previous(); }); } function next() { - $scope.$apply(function() { + $scope.$apply(function () { comicService.next(); }); } var shortcut = - /* jshint evil:true */ window.eval('window.shortcut'); - /* jshint evil:false */ - + // Firefox balks at me trying to use the "shortcut" object from // my user script. Works just fine in Chrome. I can't be bothered // to cater to one browser's stupidity. if (isStupidFox) { var shortcutRemove = - /* jshint evil:true */ window.eval('window.shortcut.remove').bind(shortcut); - /* jshint evil:false */ shortcutRemove('Left'); shortcutRemove('Right'); - + // This is a sort of replacement for "shortcut". Only supports // simple Left/Right navigation. Is missing the editor mode // shortcuts because Firefox is behaving like shit. - window.addEventListener('keydown', function(event) { + window.addEventListener('keydown', function (event) { // Only if no special keys are held down if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } - + if (event.keyCode === 37) { // LEFT previous(); @@ -78,23 +72,21 @@ var qcExt; // actively try to sabotage you? shortcut.remove('Left'); shortcut.remove('Right'); - - // jscs:disable requireCamelCaseOrUpperCaseIdentifiers + shortcut.add('Left', previous, - {disable_in_input: true}); + { disable_in_input: true }); shortcut.add('Ctrl+Left', previous); shortcut.add('Right', next, - {disable_in_input: true}); + { disable_in_input: true }); shortcut.add('Ctrl+Right', next); - shortcut.add('Q', function() { - if (qcExt.settings.editMode) { + shortcut.add('Q', function () { + if (settings.editMode) { $('input[id^="addItem"]').focus(); } - }, {disable_in_input: true}); - // jscs:enable requireCamelCaseOrUpperCaseIdentifiers + }, { disable_in_input: true }); } $log.debug('END bodyController()'); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-comicController.js b/assets/js/modules/angular/controllers/comicController.js similarity index 76% rename from assets/js/qc-ext-comicController.js rename to assets/js/modules/angular/controllers/comicController.js index 568be5a..4655508 100644 --- a/assets/js/qc-ext-comicController.js +++ b/assets/js/modules/angular/controllers/comicController.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,15 +15,11 @@ * along with this program. If not, see . */ -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.controller('comicController', ['$log', 'comicService', - function($log, comicService) { +export default function (app) { + app.controller('comicController', ['$log', 'comicService', + function ($log, comicService) { $log.debug('START comicController()'); this.comicService = comicService; $log.debug('END comicController()'); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-titleController.js b/assets/js/modules/angular/controllers/titleController.js similarity index 74% rename from assets/js/qc-ext-titleController.js rename to assets/js/modules/angular/controllers/titleController.js index fc2233d..1b5bc8d 100644 --- a/assets/js/qc-ext-titleController.js +++ b/assets/js/modules/angular/controllers/titleController.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,25 +15,21 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.controller('titleController', ['$log', '$scope', 'eventFactory', - function($log, $scope, Event) { +export default function (app) { + app.controller('titleController', ['$log', '$scope', 'eventFactory', + function ($log, $scope, Event) { $log.debug('START titleController()'); - + this.title = 'Loading Questionable Content Extension...'; - + var comicDataLoadingEvent = new Event(constants.comicdataLoadingEvent); var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -46,15 +42,15 @@ var qcExt; var self = this; - comicDataLoadingEvent.subscribe($scope, function(event, comic) { - $scope.safeApply(function() { + comicDataLoadingEvent.subscribe($scope, function (event, comic) { + $scope.safeApply(function () { self.title = 'Loading #' + comic + ' — Questionable Content'; }); }); - comicDataLoadedEvent.subscribe($scope, function(event, comicData) { - $scope.safeApply(function() { + comicDataLoadedEvent.subscribe($scope, function (event, comicData) { + $scope.safeApply(function () { if (comicData.hasData && comicData.title) { self.title = '#' + comicData.comic + ': ' + comicData.title + ' — Questionable Content'; @@ -64,7 +60,7 @@ var qcExt; } }); }); - + $log.debug('END titleController()'); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/modules/angular/decorateHttpService.js b/assets/js/modules/angular/decorateHttpService.js new file mode 100644 index 0000000..15fd9d3 --- /dev/null +++ b/assets/js/modules/angular/decorateHttpService.js @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2016-2018 Alexander Krivács Schrøder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// TODO: Since we're not using the original service at all, we might +// as well completely replace it rather than decorate it... +// http://www.bennadel.com/blog/ +// 2927-overriding-core-and-custom-services-in-angularjs.htm +export default function ($provide) { + + // Let's take over $http and make it use Greasemonkey's cross-domain + // XMLHTTPRequests instead of the browser's. + $provide.decorator('$http', function () { + + // START Code bits borrowed from angular + // (see angular's license for details) + var APPLICATION_JSON = 'application/json'; + var JSON_START = /^\[|^\{(?!\{)/; + var JSON_ENDS = { + '[': /]$/, + '{': /}$/ + }; + var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; + + function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); + } + + function isString(value) { + return typeof value === 'string'; + } + + function fromJson(json) { + return isString(json) ? JSON.parse(json) : json; + } + + function defaultHttpResponseTransform(data, headers) { + if (!isString(data)) { + return data; + } + + // Strip json vulnerability protection prefix + // and trim whitespace + var tempData = data.replace(JSON_PROTECTION_PREFIX, '') + .trim(); + + if (!tempData) { + return data; + } + + var contentType = headers('Content-Type'); + + if (contentType && + contentType.indexOf(APPLICATION_JSON) === 0 || + isJsonLike(tempData)) { + data = fromJson(tempData); + } + + return data; + } + + // END Code bits borrowed from angular + + function getHeaderFunction(headers) { + var keyedHeaders = {}; + + angular.forEach(headers, function (value) { + var splitValue = value.trim().split(':', 2); + + if (splitValue.length < 2) { + return; + } + + keyedHeaders[splitValue[0].trim()] = + splitValue[1].trim(); + }); + + return function (key) { + return keyedHeaders[key] || null; + }; + } + + var injector = angular.injector(['ng']); + var $q = injector.get('$q'); + var ourHttp = { + get: function (url, config) { + return $q(function (resolve, reject) { + GM.xmlHttpRequest({ + method: 'GET', + url: url, + headers: { + Accept: APPLICATION_JSON + }, + onload: function (gmResponse) { + var headers = getHeaderFunction( + gmResponse.responseHeaders + .split('\n')); + var responseData = gmResponse.response; + + responseData = defaultHttpResponseTransform( + responseData, headers); + var response = { + data: responseData, + status: gmResponse.status, + headers: headers, + config: config, + statusText: gmResponse.statusText + }; + + resolve(response); + }, + onerror: function (gmResponse) { + var headers = getHeaderFunction(gmResponse + .responseHeaders.split('\n')); + var responseData = gmResponse.response; + + responseData = defaultHttpResponseTransform( + responseData, headers); + var response = { + data: responseData, + status: gmResponse.status, + headers: headers, + config: config, + statusText: gmResponse.statusText + }; + + reject(response); + } + }); + }); + }, + post: function (url, data, config) { + return $q(function (resolve, reject) { + GM.xmlHttpRequest({ + method: 'POST', + url: url, + data: JSON.stringify(data), + headers: { + 'Content-Type': APPLICATION_JSON, + Accept: APPLICATION_JSON + }, + onload: function (gmResponse) { + var headers = getHeaderFunction( + gmResponse.responseHeaders + .split('\n')); + var responseData = gmResponse.response; + + responseData = defaultHttpResponseTransform( + responseData, headers); + var response = { + data: responseData, + status: gmResponse.status, + headers: headers, + config: config, + statusText: gmResponse.statusText + }; + + resolve(response); + }, + onerror: function (gmResponse) { + var headers = getHeaderFunction(gmResponse + .responseHeaders.split('\n')); + var responseData = gmResponse.response; + + responseData = defaultHttpResponseTransform( + responseData, headers); + var response = { + data: responseData, + status: gmResponse.status, + headers: headers, + config: config, + statusText: gmResponse.statusText + }; + + reject(response); + } + }); + }); + } + }; + + /* Methods/properties to implement for full compatibility: + * pendingRequests + * delete + * head + * jsonp + * post + * put + * patch + * defaults + */ + + return ourHttp; + }); +} diff --git a/assets/js/qc-ext-donutDirective.js b/assets/js/modules/angular/directives/donutDirective.js similarity index 85% rename from assets/js/qc-ext-donutDirective.js rename to assets/js/modules/angular/directives/donutDirective.js index fcdada2..14c4d7c 100644 --- a/assets/js/qc-ext-donutDirective.js +++ b/assets/js/modules/angular/directives/donutDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,13 +15,11 @@ * along with this program. If not, see . */ -var qcExt; +import variables from '../../../../generated/variables.pass2'; -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('donut', [ - function() { +export default function (app) { + app.directive('donut', [ + function () { return { restrict: 'E', scope: { @@ -33,7 +31,7 @@ var qcExt; borderSize: '@' }, controller: ['$scope', - function($scope) { + function ($scope) { function calculateRotationValues() { $scope.rotation = $scope.percent / 100 * 180; $scope.fixRotation = $scope.rotation * 2; @@ -56,13 +54,13 @@ var qcExt; } calculateRotationValues(); calculateSizeValues(); - + $scope.$watch('percent', calculateRotationValues); $scope.$watch('size', calculateSizeValues); $scope.$watch('borderSize', calculateSizeValues); } ], - template: qcExt.variables.angularTemplates.donut + template: variables.html.donut }; }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-onErrorDirective.js b/assets/js/modules/angular/directives/onErrorDirective.js similarity index 72% rename from assets/js/qc-ext-onErrorDirective.js rename to assets/js/modules/angular/directives/onErrorDirective.js index 722e13e..29f4e7e 100644 --- a/assets/js/qc-ext-onErrorDirective.js +++ b/assets/js/modules/angular/directives/onErrorDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,19 +15,15 @@ * along with this program. If not, see . */ -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('onError', function() { +export default function (app) { + app.directive('onError', function () { return { restrict: 'A', - link: function(scope, element, attrs) { - element.bind('error', function() { + link: function (scope, element, attrs) { + element.bind('error', function () { scope.$apply(attrs.onError); }); } }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcAddItemDirective.js b/assets/js/modules/angular/directives/qcAddItemDirective.js similarity index 84% rename from assets/js/qc-ext-qcAddItemDirective.js rename to assets/js/modules/angular/directives/qcAddItemDirective.js index 2b25337..73b0b3e 100644 --- a/assets/js/qc-ext-qcAddItemDirective.js +++ b/assets/js/modules/angular/directives/qcAddItemDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,21 +15,18 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcAddItem', function() { +export default function (app) { + app.directive('qcAddItem', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$http', '$scope', '$log', '$timeout', '$filter', 'comicService', 'eventFactory', - function($http, $scope, $log, $timeout, $filter, + function ($http, $scope, $log, $timeout, $filter, comicService, Event) { $log.debug('START qcAddItem()'); @@ -40,7 +37,7 @@ var qcExt; var itemsChangedEvent = new Event(constants.itemsChangedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -81,7 +78,7 @@ var qcExt; function loadItemData() { $http.get(constants.itemDataUrl) - .then(function(response) { + .then(function (response) { var itemData = []; if (response.status === 200) { itemData = response.data; @@ -91,20 +88,20 @@ var qcExt; itemData.push(addStorylineItem); itemData.push(addLocationItem); - $scope.safeApply(function() { + $scope.safeApply(function () { self.items = itemData; }); }); } loadItemData(); - + function escapeRegExp(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); } - this.searchChanged = function() { + this.searchChanged = function () { var filterText = self.itemFilterText; - + if (filterText.charAt(0) === '!') { filterText = filterText.substr(1); } else if (filterText.charAt(0) === '@') { @@ -112,7 +109,7 @@ var qcExt; } else if (filterText.charAt(0) === '#') { filterText = filterText.substr(1); } - + addCastItem.shortName = addCastTemplate + '\'' + filterText + '\''; addCastItem.name = filterText; @@ -129,9 +126,9 @@ var qcExt; var firstRun = true; this.itemFilterText = ''; - this.itemFilter = function(value) { + this.itemFilter = function (value) { var filterText = self.itemFilterText; - + var result = true; if (filterText.charAt(0) === '!') { result = value.type === 'cast'; @@ -143,19 +140,19 @@ var qcExt; result = value.type === 'storyline'; filterText = filterText.substr(1); } - + var searchRegex = new RegExp( escapeRegExp(filterText), 'i'); result = result && value.shortName.match(searchRegex) !== null; - + return result; }; // {shortName: ''}; - this.focusSearch = function() { + this.focusSearch = function () { $log.debug('qcAdditem(): #1 Search focused'); if (firstRun) { - $(dropdownId).on('shown.bs.dropdown', function() { + $(dropdownId).on('shown.bs.dropdown', function () { dropdownOpen = true; $log.debug('qcAdditem(): #4 Dropdown opened'); @@ -167,7 +164,7 @@ var qcExt; $(dropdownId + ' .dropdown-menu').width($( dropdownId).width()); }); - $(dropdownId).on('hidden.bs.dropdown', function() { + $(dropdownId).on('hidden.bs.dropdown', function () { $log.debug('qcAdditem(): #5 Dropdown closed'); dropdownOpen = false; }); @@ -179,7 +176,7 @@ var qcExt; $log.debug( 'qcAdditem(): #2 Focus was user-initiated'); triggeredFocus = true; - $timeout(function() { + $timeout(function () { if (!dropdownOpen) { $log.debug( 'qcAdditem(): #3 Toggle dropdown'); @@ -189,7 +186,7 @@ var qcExt; } }; - this.keyPress = function(event) { + this.keyPress = function (event) { if (event.keyCode === 13) { // ENTER key @@ -207,25 +204,25 @@ var qcExt; } };*/ - this.addItem = function(item) { - comicService.addItem(item).then(function(response) { + this.addItem = function (item) { + comicService.addItem(item).then(function (response) { if (response.status === 200) { itemsChangedEvent.notify(); - $scope.safeApply(function() { + $scope.safeApply(function () { self.itemFilterText = ''; }); } }); }; - itemsChangedEvent.subscribe($scope, function() { + itemsChangedEvent.subscribe($scope, function () { loadItemData(); }); $log.debug('END qcAddItem()'); }], controllerAs: 'a', - template: qcExt.variables.angularTemplates.addItem + template: variables.html.addItem }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcChangeLogDirective.js b/assets/js/modules/angular/directives/qcChangeLogDirective.js similarity index 66% rename from assets/js/qc-ext-qcChangeLogDirective.js rename to assets/js/modules/angular/directives/qcChangeLogDirective.js index ba2e5f7..c73a432 100644 --- a/assets/js/qc-ext-qcChangeLogDirective.js +++ b/assets/js/modules/angular/directives/qcChangeLogDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,42 +15,40 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcChangeLog', function() { +export default function (app) { + app.directive('qcChangeLog', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$log', 'eventFactory', '$scope', - function($log, Event, $scope) { + function ($log, Event, $scope) { $log.debug('START qcChangeLog()'); - + $log.debug(); - + this.versionUpdated = false; - this.currentVersion = GM_info.script.version; + this.currentVersion = GM.info.script.version; this.previousVersion = null; var self = this; var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - + comicDataLoadedEvent.subscribe($scope, - function() { - if (qcExt.settings.version === undefined) { + function () { + if (settings.version === undefined) { // Version is undefined. We're a new user! $log.debug('qcChangeLog(): Version undefined!'); - } else if (qcExt.settings.version !== + } else if (settings.version !== self.currentVersion) { // Version is changed. Script has been updated! // Show the change log dialog. - self.previousVersion = qcExt.settings.version; + self.previousVersion = settings.version; $log.debug('qcChangeLog(): Version different!'); } else { return; @@ -58,21 +56,22 @@ var qcExt; self.versionUpdated = true; }); - $('#changeLogDialog').on('hide.bs.modal', function() { + $('#changeLogDialog').on('hide.bs.modal', function () { $log.debug('Saving settings...'); - qcExt.settings.version = self.currentVersion; - GM_setValue(constants.settingsKey, - JSON.stringify(qcExt.settings)); + settings.version = self.currentVersion; + settings.saveSettings().then(() => { + $log.debug('Settings saved.'); + }); }); - this.close = function() { + this.close = function () { $('#changeLogDialog').modal('hide'); }; - + $log.debug('END qcChangeLog()'); }], controllerAs: 'clvm', - template: qcExt.variables.angularTemplates.changeLog + template: variables.html.changeLog }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcComicDirective.js b/assets/js/modules/angular/directives/qcComicDirective.js similarity index 72% rename from assets/js/qc-ext-qcComicDirective.js rename to assets/js/modules/angular/directives/qcComicDirective.js index ed3dc66..3460424 100644 --- a/assets/js/qc-ext-qcComicDirective.js +++ b/assets/js/modules/angular/directives/qcComicDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,26 +15,22 @@ * along with this program. If not, see . */ -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcComic', function() { +export default function (app) { + app.directive('qcComic', function () { return { restrict: 'E', transclude: true, scope: {}, - link: function(scope, element, attrs, ctrl, transclude) { - transclude(scope, function(clone) { + link: function (scope, element, attrs, ctrl, transclude) { + transclude(scope, function (clone) { element.append(clone); }); }, controller: ['comicService', - function(comicService) { + function (comicService) { this.comicService = comicService; }], controllerAs: 'c' }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcComicNavDirective.js b/assets/js/modules/angular/directives/qcComicNavDirective.js similarity index 78% rename from assets/js/qc-ext-qcComicNavDirective.js rename to assets/js/modules/angular/directives/qcComicNavDirective.js index c5bd014..6ad1824 100644 --- a/assets/js/qc-ext-qcComicNavDirective.js +++ b/assets/js/modules/angular/directives/qcComicNavDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,21 +15,18 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcComicNav', function() { +export default function (app) { + app.directive('qcComicNav', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$log', 'comicService', 'latestComic', 'eventFactory', '$scope', - function($log, comicService, latestComic, Event, $scope) { + function ($log, comicService, latestComic, Event, $scope) { $log.debug('START qcComicNav()'); var comicDataLoadedEvent = @@ -39,7 +36,7 @@ var qcExt; this.latestComic = latestComic; var self = this; - this.go = function() { + this.go = function () { $log.debug('qcComicNav.go(): ' + self.currentComic); if (self.currentComic === undefined || self.currentComic === null) { @@ -52,7 +49,7 @@ var qcExt; comicService.gotoComic(self.currentComic); }; - this.keyPress = function(event) { + this.keyPress = function (event) { if (event.keyCode === 13) { // ENTER key self.go(); @@ -60,14 +57,14 @@ var qcExt; }; comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { + function (event, comicData) { self.currentComic = comicData.comic; }); $log.debug('END qcComicNav()'); }], controllerAs: 'cn', - template: qcExt.variables.angularTemplates.comicNav + template: variables.html.comicNav }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcDateDirective.js b/assets/js/modules/angular/directives/qcDateDirective.js similarity index 76% rename from assets/js/qc-ext-qcDateDirective.js rename to assets/js/modules/angular/directives/qcDateDirective.js index 4b19b87..92049a7 100644 --- a/assets/js/qc-ext-qcDateDirective.js +++ b/assets/js/modules/angular/directives/qcDateDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,28 +15,26 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcDate', function() { +export default function (app) { + app.directive('qcDate', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$log', 'eventFactory', - function($scope, $log, Event) { + function ($scope, $log, Event) { var comicDataLoadingEvent = new Event(constants.comicdataLoadingEvent); var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - + $log.debug('START qcDate()'); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { @@ -49,19 +47,19 @@ var qcExt; }; var self = this; - this.settings = qcExt.settings; + this.settings = settings; this.date = null; this.approximateDate = false; comicDataLoadingEvent.subscribe($scope, - function() { - $scope.safeApply(function() { + function () { + $scope.safeApply(function () { self.date = null; self.approximateDate = false; }); }); comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { self.approximateDate = !comicData.isAccuratePublishDate; var publishDate = comicData.publishDate; $log.debug('qcDate(): ', publishDate); @@ -74,11 +72,11 @@ var qcExt; } }); }); - + $log.debug('END qcDate()'); }], controllerAs: 'd', - template: qcExt.variables.angularTemplates.date + template: variables.html.date }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcEditComicDataDirective.js b/assets/js/modules/angular/directives/qcEditComicDataDirective.js similarity index 69% rename from assets/js/qc-ext-qcEditComicDataDirective.js rename to assets/js/modules/angular/directives/qcEditComicDataDirective.js index bb749d1..313351f 100644 --- a/assets/js/qc-ext-qcEditComicDataDirective.js +++ b/assets/js/modules/angular/directives/qcEditComicDataDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,26 +15,23 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcEditComicData', function() { +export default function (app) { + app.directive('qcEditComicData', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$log', 'eventFactory', 'comicService', - function($scope, $log, Event, comicService) { + function ($scope, $log, Event, comicService) { var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); var itemsChangedEvent = new Event(constants.itemsChangedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -48,13 +45,13 @@ var qcExt; var self = this; comicDataLoadedEvent - .subscribe($scope, function(event, comicData) { - $scope.safeApply(function() { - var editData = {comicData: comicData}; + .subscribe($scope, function (event, comicData) { + $scope.safeApply(function () { + var editData = { comicData: comicData }; if (comicData.hasData) { angular.forEach(comicData.items, - function(value) { + function (value) { if (!(value.type in editData)) { editData[value.type] = {}; @@ -69,34 +66,34 @@ var qcExt; }); }); - $('#editComicDataDialog').on('show.bs.modal', function() { + $('#editComicDataDialog').on('show.bs.modal', function () { // If something needs to be done, do it here. }); - this.remove = function(item) { - comicService.removeItem(item).then(function(response) { + this.remove = function (item) { + comicService.removeItem(item).then(function (response) { if (response.status === 200) { itemsChangedEvent.notify(); } }); }; - this.changeGuestComic = function() { + this.changeGuestComic = function () { comicService.setGuestComic( self.editData.comicData.isGuestComic); }; - this.changeNonCanon = function() { + this.changeNonCanon = function () { comicService.setNonCanon( self.editData.comicData.isNonCanon); }; - this.close = function() { + this.close = function () { $('#editComicDataDialog').modal('hide'); }; }], controllerAs: 'ecdvm', - template: qcExt.variables.angularTemplates.editComicData + template: variables.html.editComicData }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcExtraDirective.js b/assets/js/modules/angular/directives/qcExtraDirective.js similarity index 83% rename from assets/js/qc-ext-qcExtraDirective.js rename to assets/js/modules/angular/directives/qcExtraDirective.js index a8ddbec..9010872 100644 --- a/assets/js/qc-ext-qcExtraDirective.js +++ b/assets/js/modules/angular/directives/qcExtraDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,19 +15,18 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; +export default function (app) { -(function(qcExt) { - 'use strict'; - function Controller($scope, $log, comicService, latestComic, Event, $sce) { var comicDataLoadingEvent = new Event(constants.comicdataLoadingEvent); var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); var comicDataErrorEvent = new Event(constants.comicdataErrorEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { @@ -43,7 +42,7 @@ var qcExt; var self = this; this.comicService = comicService; - this.settings = qcExt.settings; + this.settings = settings; this.constants = constants; this.items = {}; this.allItems = {}; @@ -68,13 +67,13 @@ var qcExt; self.messages.push('Loading...'); } - comicDataLoadingEvent.subscribe($scope, function() { + comicDataLoadingEvent.subscribe($scope, function () { $scope.safeApply(loading); }); comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { reset(); if (self.settings.editMode && @@ -97,8 +96,6 @@ var qcExt; self.editorData.missing.title.any || self.editorData.missing.tagline.any; - /* jshint eqeqeq:false */ - /* jscs:disable maximumLineLength */ if (self.editorData.missing.cast.first == comicService.comic) { self.editorData.missing.cast.first = null; } @@ -119,17 +116,15 @@ var qcExt; if (self.editorData.missing.storyline.last == comicService.comic) { self.editorData.missing.storyline.last = null; } - /* jscs:enable maximumLineLength */ - /* jshint eqeqeq:true */ } - + function processItem(item) { if (!(item.type in self.items)) { self.items[item.type] = []; } self.items[item.type].push(item); } - + function processAllItem(item) { if (!(item.type in self.allItems)) { self.allItems[item.type] = []; @@ -140,10 +135,10 @@ var qcExt; if (!comicData.hasData) { self.messages.push( 'This strip has no navigation data yet' - ); + ); self.hasWarning = true; - - if (qcExt.settings.showAllMembers) { + + if (settings.showAllMembers) { angular.forEach(comicData.allItems, processAllItem); } return; @@ -151,9 +146,9 @@ var qcExt; var hasCast = false; var hasLocation = false; - var hasStoryline = false; + //var hasStoryline = false; angular.forEach(comicData.items, - function(item) { + function (item) { processItem(item); if (item.type === 'cast') { @@ -161,11 +156,11 @@ var qcExt; } else if (item.type === 'location') { hasLocation = true; } else if (item.type === 'storyline') { - hasStoryline = true; + //hasStoryline = true; } } ); - if (qcExt.settings.showAllMembers) { + if (settings.showAllMembers) { angular.forEach(comicData.allItems, processAllItem); } @@ -186,12 +181,12 @@ var qcExt; self.missingDataInfo.push('a tagline'); } - var currentVersion = GM_info.script.version; - if (qcExt.settings.version === undefined) { + var currentVersion = GM.info.script.version; + if (settings.version === undefined) { // Version is undefined. We're a new user! $log.debug('qcExtra(): Version undefined!'); self.showWelcomeMessage = true; - } else if (qcExt.settings.version !== + } else if (settings.version !== currentVersion) { // Version is changed. Script has been updated! self.showUpdateMessage = true; @@ -200,9 +195,9 @@ var qcExt; }); comicDataErrorEvent.subscribe($scope, - function(event, data) { + function (event, data) { $scope.safeApply(reset); - $scope.safeApply(function() { + $scope.safeApply(function () { if (data.status !== 503) { self.messages.push('Error communicating with server'); self.hasError = true; @@ -212,7 +207,7 @@ var qcExt; }); }); - this.getTypeDescription = function(type) { + this.getTypeDescription = function (type) { switch (type) { case 'cast': return 'Cast Members'; @@ -220,7 +215,7 @@ var qcExt; return 'Storylines'; case 'location': return 'Locations'; - + case 'all-cast': return $sce.trustAsHtml('Cast Members
' + '(Non-Present)'); @@ -233,31 +228,31 @@ var qcExt; } }; - this.openSettings = function() { + this.openSettings = function () { $('#settingsDialog').modal('show'); }; - this.editComicData = function() { + this.editComicData = function () { $('#editComicDataDialog').modal('show'); }; - this.showDetailsFor = function(item) { + this.showDetailsFor = function (item) { $('#itemDetailsDialog').data('itemId', item.id); $('#itemDetailsDialog').modal('show'); }; - - this.enableTagModeFor = function(item) { + + this.enableTagModeFor = function (item) { $log.debug(item); }; - this.showChangeLog = function() { + this.showChangeLog = function () { self.showWelcomeMessage = false; self.showUpdateMessage = false; $('#changeLogDialog').modal('show'); }; } - qcExt.app.directive('qcExtra', function() { + app.directive('qcExtra', function () { return { restrict: 'E', replace: true, @@ -265,7 +260,7 @@ var qcExt; controller: ['$scope', '$log', 'comicService', 'latestComic', 'eventFactory', '$sce', Controller], controllerAs: 'e', - template: qcExt.variables.angularTemplates.extra + template: variables.html.extra }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcExtraNavDirective.js b/assets/js/modules/angular/directives/qcExtraNavDirective.js similarity index 78% rename from assets/js/qc-ext-qcExtraNavDirective.js rename to assets/js/modules/angular/directives/qcExtraNavDirective.js index a39cc4d..05abccf 100644 --- a/assets/js/qc-ext-qcExtraNavDirective.js +++ b/assets/js/modules/angular/directives/qcExtraNavDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,12 +15,10 @@ * along with this program. If not, see . */ -var qcExt; +import variables from '../../../../generated/variables.pass2'; -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcExtraNav', function() { +export default function (app) { + app.directive('qcExtraNav', function () { return { restrict: 'E', scope: { @@ -36,7 +34,7 @@ var qcExt; nameTitle: '@', clickAction: '&' }, - template: qcExt.variables.angularTemplates.extraNav + template: variables.html.extraNav }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcItemDetailsDirective.js b/assets/js/modules/angular/directives/qcItemDetailsDirective.js similarity index 81% rename from assets/js/qc-ext-qcItemDetailsDirective.js rename to assets/js/modules/angular/directives/qcItemDetailsDirective.js index b72c796..fdbf24b 100644 --- a/assets/js/qc-ext-qcItemDetailsDirective.js +++ b/assets/js/modules/angular/directives/qcItemDetailsDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,28 +15,26 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcItemDetails', function() { +export default function (app) { + app.directive('qcItemDetails', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$log', '$http', '$scope', 'colorService', 'comicService', 'messageReportingService', 'styleService', - function($log, $http, $scope, colorService, + function ($log, $http, $scope, colorService, comicService, messageReportingService, styleService) { var self = this; this.isLoading = true; - this.settings = qcExt.settings; + this.settings = settings; - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -46,42 +44,42 @@ var qcExt; this.$apply(fn); } }; - + function getItemDetails() { var itemId = $('#itemDetailsDialog').data('itemId'); $log.debug('qcItemDetails::showModal() - item id:', itemId); - + function handleRelationData(response) { if (response.status === 200) { var relationData = response.data; - - $.each(relationData, function(_, relation) { + + $.each(relationData, function (_, relation) { relation.percentage = relation.count / self.itemData.appearances * 100; }); - + return relationData; } return null; } - + function handleItemFriendsData(response) { var friends = handleRelationData(response); if (friends === null) { friends = []; } - $scope.safeApply(function() { + $scope.safeApply(function () { self.itemData.friends = friends; }); } - + function handleItemLocationsData(response) { var locations = handleRelationData(response); if (locations === null) { locations = []; } - $scope.safeApply(function() { + $scope.safeApply(function () { self.itemData.locations = locations; }); } @@ -105,17 +103,17 @@ var qcExt; // If the color changes, also update the // highlight color - $scope.safeApply(function() { + $scope.safeApply(function () { self.itemData = itemData; self.isLoading = false; - $scope.$watch(function() { + $scope.$watch(function () { return self.itemData.color; - }, function() { + }, function () { itemData.highlightColor = colorService - .createTintOrShade( - itemData.color); + .createTintOrShade( + itemData.color); }); }); @@ -136,13 +134,13 @@ var qcExt; } $('#itemDetailsDialog').on('show.bs.modal', getItemDetails); - - this.showInfoFor = function(id) { + + this.showInfoFor = function (id) { $('#itemDetailsDialog').data('itemId', id); getItemDetails(); }; - this.keypress = function(event, property) { + this.keypress = function (event, property) { if (event.keyCode === 13) { // ENTER key self.update(property); @@ -163,21 +161,21 @@ var qcExt; return response; } - this.update = function(property) { + this.update = function (property) { function updateItemColor(response) { if (response.status === 200) { if (property === 'color') { $log.debug('qcItemDetails::update() - ' + - 'update item color'); + 'update item color'); styleService.removeItemStyle( self.itemData.id); } } return onSuccessRefreshElseErrorLog(response); } - + var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, item: self.itemData.id, property: property, value: self.itemData[property] @@ -186,18 +184,17 @@ var qcExt; .then(updateItemColor, onErrorLog); }; - this.goToComic = function(comic) { + this.goToComic = function (comic) { comicService.gotoComic(comic); self.close(); }; - this.close = function() { + this.close = function () { $('#itemDetailsDialog').modal('hide'); }; }], controllerAs: 'idvm', - template: qcExt.variables.angularTemplates.itemDetails + template: variables.html.itemDetails }; }); -})(qcExt || (qcExt = {})); - +} diff --git a/assets/js/qc-ext-qcNavDirective.js b/assets/js/modules/angular/directives/qcNavDirective.js similarity index 74% rename from assets/js/qc-ext-qcNavDirective.js rename to assets/js/modules/angular/directives/qcNavDirective.js index 247206a..01155a5 100644 --- a/assets/js/qc-ext-qcNavDirective.js +++ b/assets/js/modules/angular/directives/qcNavDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,17 +15,15 @@ * along with this program. If not, see . */ -var qcExt; +import variables from '../../../../generated/variables.pass2'; -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcNav', function() { +export default function (app) { + app.directive('qcNav', function () { return { restrict: 'E', - scope: {randomComic: '='}, + scope: { randomComic: '=' }, controller: ['$scope', 'comicService', 'latestComic', - function($scope, comicService, latestComic) { + function ($scope, comicService, latestComic) { this.comicService = comicService; function updateRandomComic() { @@ -35,31 +33,31 @@ var qcExt; updateRandomComic(); - this.first = function(event) { + this.first = function (event) { event.preventDefault(); event.stopPropagation(); comicService.first(); }; - this.previous = function(event) { + this.previous = function (event) { event.preventDefault(); event.stopPropagation(); comicService.previous(); }; - this.next = function(event) { + this.next = function (event) { event.preventDefault(); event.stopPropagation(); comicService.next(); }; - this.last = function(event) { + this.last = function (event) { event.preventDefault(); event.stopPropagation(); comicService.last(); }; - this.random = function(event) { + this.random = function (event) { event.preventDefault(); event.stopPropagation(); @@ -68,7 +66,7 @@ var qcExt; }; }], controllerAs: 'n', - template: qcExt.variables.angularTemplates.navigation + template: variables.html.navigation }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcNewsDirective.js b/assets/js/modules/angular/directives/qcNewsDirective.js similarity index 83% rename from assets/js/qc-ext-qcNewsDirective.js rename to assets/js/modules/angular/directives/qcNewsDirective.js index 3062f42..0e29dff 100644 --- a/assets/js/qc-ext-qcNewsDirective.js +++ b/assets/js/modules/angular/directives/qcNewsDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,26 +15,22 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcNews', function() { +export default function (app) { + app.directive('qcNews', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$sce', '$compile', 'eventFactory', - function($scope, $sce, $compile, Event) { + function ($scope, $sce, $compile, Event) { var comicDataLoadingEvent = new Event(constants.comicdataLoadingEvent); var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { @@ -67,14 +63,14 @@ var qcExt; this.news = $sce.trustAsHtml('Loading...'); comicDataLoadingEvent.subscribe($scope, - function() { - $scope.safeApply(function() { + function () { + $scope.safeApply(function () { self.news = $sce.trustAsHtml('Loading...'); }); }); comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { self.news = $sce.trustAsHtml(nl2br( angularizeLinks(comicData.news), false)); }); @@ -85,4 +81,4 @@ var qcExt; '
' }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcRibbonDirective.js b/assets/js/modules/angular/directives/qcRibbonDirective.js similarity index 70% rename from assets/js/qc-ext-qcRibbonDirective.js rename to assets/js/modules/angular/directives/qcRibbonDirective.js index 79eaf5f..e095bec 100644 --- a/assets/js/qc-ext-qcRibbonDirective.js +++ b/assets/js/modules/angular/directives/qcRibbonDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,24 +15,22 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcRibbon', function() { +export default function (app) { + app.directive('qcRibbon', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', 'eventFactory', - function($scope, Event) { + function ($scope, Event) { var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { @@ -43,23 +41,23 @@ var qcExt; this.$apply(fn); } }; - - this.settings = qcExt.settings; + + this.settings = settings; this.isNonCanon = false; this.isGuestComic = false; - this.isSmall = qcExt.settings.showSmallRibbonByDefault; + this.isSmall = settings.showSmallRibbonByDefault; var self = this; comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { self.isNonCanon = comicData.isNonCanon; self.isGuestComic = comicData.isGuestComic; }); }); }], controllerAs: 'r', - template: qcExt.variables.angularTemplates.ribbon + template: variables.html.ribbon }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcSetPublishDateDirective.js b/assets/js/modules/angular/directives/qcSetPublishDateDirective.js similarity index 79% rename from assets/js/qc-ext-qcSetPublishDateDirective.js rename to assets/js/modules/angular/directives/qcSetPublishDateDirective.js index c106282..30141de 100644 --- a/assets/js/qc-ext-qcSetPublishDateDirective.js +++ b/assets/js/modules/angular/directives/qcSetPublishDateDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,21 +15,18 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcSetPublishDate', function() { +export default function (app) { + app.directive('qcSetPublishDate', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$log', 'comicService', 'eventFactory', 'messageReportingService', - function($scope, $log, comicService, Event, + function ($scope, $log, comicService, Event, messageReportingService) { $log.debug('START qcSetPublishDate()'); @@ -40,7 +37,7 @@ var qcExt; var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -51,14 +48,14 @@ var qcExt; } }; - this.keyPress = function(event) { + this.keyPress = function (event) { if (event.keyCode === 13) { // ENTER key self.setPublishDate(); } }; - this.setPublishDate = function() { + this.setPublishDate = function () { if (self.publishDate === null || self.publishDate === undefined) { // Error @@ -72,8 +69,8 @@ var qcExt; this.publishDate = ''; comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { var publishDate = comicData.publishDate; if (publishDate !== null && publishDate !== undefined) { @@ -90,7 +87,7 @@ var qcExt; $log.debug('END qcSetPublishDate()'); }], controllerAs: 's', - template: qcExt.variables.angularTemplates.setPublishDate + template: variables.html.setPublishDate }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcSetTaglineDirective.js b/assets/js/modules/angular/directives/qcSetTaglineDirective.js similarity index 74% rename from assets/js/qc-ext-qcSetTaglineDirective.js rename to assets/js/modules/angular/directives/qcSetTaglineDirective.js index 28c89f8..c53e736 100644 --- a/assets/js/qc-ext-qcSetTaglineDirective.js +++ b/assets/js/modules/angular/directives/qcSetTaglineDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,20 +15,17 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcSetTagline', function() { +export default function (app) { + app.directive('qcSetTagline', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$log', 'comicService', 'eventFactory', - function($scope, $log, comicService, Event) { + function ($scope, $log, comicService, Event) { $log.debug('START qcSetTagline()'); var self = this; @@ -38,7 +35,7 @@ var qcExt; var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -49,21 +46,21 @@ var qcExt; } }; - this.keyPress = function(event) { + this.keyPress = function (event) { if (event.keyCode === 13) { // ENTER key self.setTagline(); } }; - this.setTagline = function() { + this.setTagline = function () { comicService.setTagline(self.tagline); }; this.tagline = ''; comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { self.tagline = comicData.tagline; }); }); @@ -71,7 +68,7 @@ var qcExt; $log.debug('END qcSetTagline()'); }], controllerAs: 's', - template: qcExt.variables.angularTemplates.setTagline + template: variables.html.setTagline }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcSetTitleDirective.js b/assets/js/modules/angular/directives/qcSetTitleDirective.js similarity index 74% rename from assets/js/qc-ext-qcSetTitleDirective.js rename to assets/js/modules/angular/directives/qcSetTitleDirective.js index 7655dc1..61369ce 100644 --- a/assets/js/qc-ext-qcSetTitleDirective.js +++ b/assets/js/modules/angular/directives/qcSetTitleDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,20 +15,17 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcSetTitle', function() { +export default function (app) { + app.directive('qcSetTitle', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', '$log', 'comicService', 'eventFactory', - function($scope, $log, comicService, Event) { + function ($scope, $log, comicService, Event) { $log.debug('START qcSetTitle()'); var self = this; @@ -38,7 +35,7 @@ var qcExt; var comicDataLoadedEvent = new Event(constants.comicdataLoadedEvent); - $scope.safeApply = function(fn) { + $scope.safeApply = function (fn) { var phase = this.$root.$$phase; if (phase === '$apply' || phase === '$digest') { if (fn && typeof fn === 'function') { @@ -49,21 +46,21 @@ var qcExt; } }; - this.keyPress = function(event) { + this.keyPress = function (event) { if (event.keyCode === 13) { // ENTER key self.setTitle(); } }; - this.setTitle = function() { + this.setTitle = function () { comicService.setTitle(self.title); }; this.title = ''; comicDataLoadedEvent.subscribe($scope, - function(event, comicData) { - $scope.safeApply(function() { + function (event, comicData) { + $scope.safeApply(function () { self.title = comicData.title; }); }); @@ -71,7 +68,7 @@ var qcExt; $log.debug('END qcSetTitle()'); }], controllerAs: 's', - template: qcExt.variables.angularTemplates.setTitle + template: variables.html.setTitle }; }); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-qcSettingsDirective.js b/assets/js/modules/angular/directives/qcSettingsDirective.js similarity index 62% rename from assets/js/qc-ext-qcSettingsDirective.js rename to assets/js/modules/angular/directives/qcSettingsDirective.js index e503788..8b9df9c 100644 --- a/assets/js/qc-ext-qcSettingsDirective.js +++ b/assets/js/modules/angular/directives/qcSettingsDirective.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,44 +15,41 @@ * along with this program. If not, see . */ -/* global constants */ +import settings from '../../settings'; +import variables from '../../../../generated/variables.pass2'; -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.directive('qcSettings', function() { +export default function (app) { + app.directive('qcSettings', function () { return { restrict: 'E', replace: true, scope: {}, controller: ['$scope', 'comicService', '$log', - function($scope, comicService, $log) { + function ($scope, comicService, $log) { var self = this; - this.settings = qcExt.settings; - - $scope.$watchGroup([function() { + this.settings = settings; + + $scope.$watchGroup([function () { return self.settings.showAllMembers; - }, function() { + }, function () { return self.settings.editMode; - }], function() { + }], function () { comicService.refreshComicData(); }); - - $('#settingsDialog').on('hide.bs.modal', function() { + + $('#settingsDialog').on('hide.bs.modal', function () { $log.debug('Saving settings...'); - GM_setValue(constants.settingsKey, - JSON.stringify(self.settings)); + settings.saveSettings().then(() => { + $log.debug('Settings saved.'); + }); }); - this.close = function() { + this.close = function () { $('#settingsDialog').modal('hide'); }; }], controllerAs: 'svm', - template: qcExt.variables.angularTemplates.settings + template: variables.html.settings }; }); -})(qcExt || (qcExt = {})); - +} diff --git a/assets/js/module.js b/assets/js/modules/angular/run.js similarity index 66% rename from assets/js/module.js rename to assets/js/modules/angular/run.js index 23bdf08..512658e 100644 --- a/assets/js/module.js +++ b/assets/js/modules/angular/run.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,15 +15,12 @@ * along with this program. If not, see . */ -var qcExt; +import settings from './../settings'; -(function(qcExt) { - 'use strict'; - - qcExt.app = angular.module('qc-spa', ['ui.router']); - qcExt.app.run(['$rootScope', 'comicService', 'startComic', - function($rootScope, comicService, startComic) { - $rootScope.settings = qcExt.settings; +export default function (app) { + app.run(['$rootScope', 'comicService', 'startComic', + function ($rootScope, comicService, startComic) { + $rootScope.settings = settings; comicService.gotoComic(startComic); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-colorService.js b/assets/js/modules/angular/services/colorService.js similarity index 89% rename from assets/js/qc-ext-colorService.js rename to assets/js/modules/angular/services/colorService.js index 9f69e0e..1ba1fa1 100644 --- a/assets/js/qc-ext-colorService.js +++ b/assets/js/modules/angular/services/colorService.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,13 +18,9 @@ // Parts based on code from: // http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.service('colorService', ['$log', - function($log) { +export default function (app) { + app.service('colorService', ['$log', + function ($log) { $log.debug('START colorService()'); function hue2rgb(p, q, t) { @@ -62,7 +58,7 @@ var qcExt; * @param {number} b The blue color value * @return Array The HSL representation */ - this.rgbToHsl = function(r, g, b) { + this.rgbToHsl = function (r, g, b) { r /= 255; g /= 255; b /= 255; @@ -109,7 +105,7 @@ var qcExt; * @param {number} l The lightness * @return Array The RGB representation */ - this.hslToRgb = function(h, s, l) { + this.hslToRgb = function (h, s, l) { var r; var g; var b; @@ -143,7 +139,7 @@ var qcExt; * @param {number} b The blue color value * @return Array The HSV representation */ - this.rgbToHsv = function(r, g, b) { + this.rgbToHsv = function (r, g, b) { r = r / 255; g = g / 255; b = b / 255; @@ -190,7 +186,7 @@ var qcExt; * @param {number} v The value * @return Array The RGB representation */ - this.hsvToRgb = function(h, s, v) { + this.hsvToRgb = function (h, s, v) { var r; var g; var b; @@ -246,38 +242,34 @@ var qcExt; ]; }; - this.hexColorToRgb = function(hexColor) { + this.hexColorToRgb = function (hexColor) { if (hexColor.charAt(0) === '#') { hexColor = hexColor.substring(1); // Strip # } var rgb = parseInt(hexColor, 16); // Convert rrggbb to decimal - /* jshint bitwise:false */ var r = rgb >> 16 & 0xff; // Extract red var g = rgb >> 8 & 0xff; // Extract green var b = rgb & 0xff; // Extract blue - /* jshint bitwise:true */ return [r, g, b]; }; - this.rgbToHexColor = function(r, g, b) { - /* jshint bitwise:false */ + this.rgbToHexColor = function (r, g, b) { return '#' + ((1 << 24) + (r << 16) + (g << 8) + b) .toString(16).slice(1); - /* jshint bitwise:true */ }; - this.getRgbRelativeLuminance = function(r, g, b) { + this.getRgbRelativeLuminance = function (r, g, b) { return 0.2126 * r + 0.7152 * g + 0.0722 * b; // Per ITU-R BT.709 }; - - this.createTintOrShade = function(hexColor, iterations) { + + this.createTintOrShade = function (hexColor, iterations) { if (typeof iterations === 'undefined') { iterations = 1; } - + var rgb = this.hexColorToRgb(hexColor); var hsl = this.rgbToHsl(rgb[0], rgb[1], rgb[2]); - + var tint = hsl[2] < 0.5; for (var i = iterations; i > 0; i--) { @@ -300,4 +292,4 @@ var qcExt; $log.debug('END colorService()'); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-comicService.js b/assets/js/modules/angular/services/comicService.js similarity index 78% rename from assets/js/qc-ext-comicService.js rename to assets/js/modules/angular/services/comicService.js index 8200310..5c3bb69 100644 --- a/assets/js/qc-ext-comicService.js +++ b/assets/js/modules/angular/services/comicService.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,17 +15,15 @@ * along with this program. If not, see . */ -/* global constants */ +import constants from '../../../constants'; -var qcExt; +import settings from '../../settings'; -(function(qcExt) { - 'use strict'; - - qcExt.app.service('comicService', ['$log', '$stateParams', '$location', +export default function (app) { + app.service('comicService', ['$log', '$stateParams', '$location', '$rootScope', '$http', 'latestComic', 'eventFactory', 'colorService', 'styleService', 'messageReportingService', - function($log, $stateParams, $location, + function ($log, $stateParams, $location, $scope, $http, latestComic, Event, colorService, styleService, messageReportingService) { $log.debug('START comicService()'); @@ -49,6 +47,8 @@ var qcExt; comic = latestComic; } + $log.debug('comicService:updateComic(): Comic is', comic); + self.comic = comic; self.nextComic = self.comic + 1 > latestComic ? latestComic : self.comic + 1; @@ -58,12 +58,12 @@ var qcExt; self.comicExtension = constants.comicExtensions[comicExtensionIndex]; - if (qcExt.settings.scrollToTop) { + if (settings.scrollToTop) { $(window).scrollTop(0); } } - $scope.$on('$stateChangeSuccess', function() { + $scope.$on('$stateChangeSuccess', function () { updateComic(); self.refreshComicData(); }); @@ -78,27 +78,27 @@ var qcExt; return response; } - this.refreshComicData = function() { + this.refreshComicData = function () { if (typeof self.comic === 'undefined') { $log.debug('comicService::refreshComicData() called ' + 'before the comicService was properly initialized. ' + 'Ignored.'); return; } - + comicDataLoadingEvent.notify(self.comic); var comicDataUrl = constants.comicDataUrl + self.comic; var urlParameters = {}; - if (qcExt.settings.editMode) { - urlParameters.token = qcExt.settings.editModeToken; + if (settings.editMode) { + urlParameters.token = settings.editModeToken; } - if (qcExt.settings.skipGuest) { + if (settings.skipGuest) { urlParameters.exclude = 'guest'; - } else if (qcExt.settings.skipNonCanon) { + } else if (settings.skipNonCanon) { urlParameters.exclude = 'non-canon'; } - if (qcExt.settings.showAllMembers) { + if (settings.showAllMembers) { urlParameters.include = 'all'; } var urlQuery = $.param(urlParameters); @@ -106,8 +106,9 @@ var qcExt; comicDataUrl += '?' + urlQuery; } + $log.debug('comicService:refreshComicData(): URL is', comicDataUrl); $http.get(comicDataUrl) - .then(function(response) { + .then(function (response) { if (response.status === 503) { comicDataErrorEvent.notify(response); return; @@ -117,9 +118,8 @@ var qcExt; comicDataErrorEvent.notify(response); return; } - + function fixItem(item) { - /* jshint eqeqeq:false */ if (item.first == self.comic) { item.first = null; } @@ -127,7 +127,6 @@ var qcExt; if (item.last == self.comic) { item.last = null; } - /* jshint eqeqeq:true */ styleService.addItemStyle(item.id, item.color); @@ -147,9 +146,9 @@ var qcExt; self.previousComic = self.comic - 1 < 1 ? 1 : self.comic - 1; } - + angular.forEach(comicData.items, fixItem); - if (qcExt.settings.showAllMembers) { + if (settings.showAllMembers) { angular.forEach(comicData.allItems, fixItem); } } else { @@ -157,8 +156,8 @@ var qcExt; latestComic : self.comic + 1; self.previousComic = self.comic - 1 < 1 ? 1 : self.comic - 1; - - if (qcExt.settings.showAllMembers) { + + if (settings.showAllMembers) { angular.forEach(comicData.allItems, fixItem); } } @@ -166,7 +165,7 @@ var qcExt; comicData.comic = self.comic; self.comicData = comicData; comicDataLoadedEvent.notify(self.comicData); - }, function(errorResponse) { + }, function (errorResponse) { onErrorLog(errorResponse); comicDataErrorEvent.notify(errorResponse); }); @@ -181,9 +180,9 @@ var qcExt; return response; } - this.addItem = function(item) { + this.addItem = function (item) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, item: item }; @@ -191,9 +190,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.removeItem = function(item) { + this.removeItem = function (item) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, item: item }; @@ -201,9 +200,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.setTitle = function(title) { + this.setTitle = function (title) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, title: title }; @@ -211,9 +210,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.setTagline = function(tagline) { + this.setTagline = function (tagline) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, tagline: tagline }; @@ -221,9 +220,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.setPublishDate = function(publishDate, isAccurate) { + this.setPublishDate = function (publishDate, isAccurate) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, publishDate: publishDate, isAccuratePublishDate: isAccurate @@ -232,9 +231,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.setGuestComic = function(value) { + this.setGuestComic = function (value) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, value: value }; @@ -242,9 +241,9 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.setNonCanon = function(value) { + this.setNonCanon = function (value) { var data = { - token: qcExt.settings.editModeToken, + token: settings.editModeToken, comic: self.comic, value: value }; @@ -252,37 +251,37 @@ var qcExt; .then(onSuccessRefreshElseErrorLog, onErrorLog); }; - this.gotoComic = function(comicNo) { + this.gotoComic = function (comicNo) { $location.url('/view.php?comic=' + comicNo); }; - this.canFallback = function() { + this.canFallback = function () { return comicExtensionIndex < constants.comicExtensions.length - 1; }; - this.tryFallback = function() { + this.tryFallback = function () { comicExtensionIndex++; self.comicExtension = constants .comicExtensions[comicExtensionIndex]; }; - this.first = function() { + this.first = function () { self.gotoComic(1); }; - this.previous = function() { + this.previous = function () { self.gotoComic(self.previousComic); }; - this.next = function() { + this.next = function () { self.gotoComic(self.nextComic); }; - this.last = function() { + this.last = function () { self.gotoComic(latestComic); }; $log.debug('END comicService()'); }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-eventFactory.js b/assets/js/modules/angular/services/eventFactory.js similarity index 72% rename from assets/js/qc-ext-eventFactory.js rename to assets/js/modules/angular/services/eventFactory.js index db0b986..844e508 100644 --- a/assets/js/qc-ext-eventFactory.js +++ b/assets/js/modules/angular/services/eventFactory.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,24 +15,20 @@ * along with this program. If not, see . */ -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.factory('eventFactory', ['$rootScope', '$log', - function($rootScope, $log) { - var eventFactory = function(eventName) { +export default function (app) { + app.factory('eventFactory', ['$rootScope', '$log', + function ($rootScope, $log) { + var eventFactory = function (eventName) { this.eventName = eventName; }; - eventFactory.prototype.subscribe = function(scope, callback) { + eventFactory.prototype.subscribe = function (scope, callback) { var handle = $rootScope.$on(this.eventName, callback); scope.$on('$destroy', handle); }; - eventFactory.prototype.notify = function(data) { + eventFactory.prototype.notify = function (data) { var eventData = [this.eventName]; if (typeof data !== 'undefined') { @@ -45,4 +41,4 @@ var qcExt; return eventFactory; }]); -})(qcExt || (qcExt = {})); +} diff --git a/assets/js/qc-ext-messageReportingService.js b/assets/js/modules/angular/services/messageReportingService.js similarity index 79% rename from assets/js/qc-ext-messageReportingService.js rename to assets/js/modules/angular/services/messageReportingService.js index 9d86af5..0a62786 100644 --- a/assets/js/qc-ext-messageReportingService.js +++ b/assets/js/modules/angular/services/messageReportingService.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Alexander Krivács Schrøder + * Copyright (C) 2016-2018 Alexander Krivács Schrøder * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,20 +15,16 @@ * along with this program. If not, see . */ -var qcExt; - -(function(qcExt) { - 'use strict'; - - qcExt.app.service('messageReportingService', ['$log', '$timeout', - function($log, $timeout) { +export default function (app) { + app.service('messageReportingService', ['$log', '$timeout', + function ($log, $timeout) { $log.debug('START messageReportingService()'); - + var messageQueue = []; var isProcessing = false; - + function escapeHtml(text) { - return text.replace(/[\"&'\/<>]/g, function(a) { + return text.replace(/["&'/<>]/g, function (a) { return { '"': '"', '&': '&', @@ -39,16 +35,16 @@ var qcExt; }[a]; }); } - + function processMessages() { isProcessing = true; - + var nextMessage = messageQueue.shift(); if (typeof nextMessage === 'undefined') { isProcessing = false; return; } - + var unique = Math.random().toString(36).slice(-5); var messageHtml = '