{{'SIMPLE_TRANSLATION_ID' | oplTranslate}}
27 | * 28 | * 29 | *{{'TRANSLATION_WITH_PARAMETERS_ID' | oplTranslate:translationParameters}}
30 | * 31 | * @class TranslateFilter 32 | */ 33 | function TranslateFilter(oplI18nService) { 34 | 35 | /** 36 | * Translates an id into the appropriated text. 37 | * 38 | * @method translate 39 | * @param {String} id The id of the translation 40 | * @param {Object} [parameters] Parameters with for each parameter the key as the placeholder to replace and the 41 | * value as the placeholder substitution string 42 | * @return {String} The translated string 43 | */ 44 | return function(id, parameters) { 45 | return oplI18nService.translate(id, parameters); 46 | }; 47 | 48 | } 49 | 50 | app.filter('oplTranslate', TranslateFilter); 51 | TranslateFilter.$inject = ['oplI18nService']; 52 | 53 | })(angular.module('ov.player')); 54 | -------------------------------------------------------------------------------- /src/components/shared/i18n/i18n.service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @module ov.player 5 | */ 6 | 7 | (function(angular, app) { 8 | 9 | /** 10 | * Defines an internationalization service to manage string translations. 11 | * 12 | * @class oplI18nService 13 | */ 14 | function oplI18nService(oplI18nTranslations) { 15 | var currentLanguage = navigator.language || navigator.browserLanguage; 16 | 17 | /** 18 | * Tests if a language is supported. 19 | * 20 | * @method isLanguageSupported 21 | * @param {String} language The language code to test (e.g en-CA) 22 | * @return {Boolean} true if supported, false otherwise 23 | */ 24 | function isLanguageSupported(language) { 25 | return Object.keys(oplI18nTranslations).indexOf(language) >= 0; 26 | } 27 | 28 | /** 29 | * Sets current language. 30 | * 31 | * @method setLanguage 32 | * @param {String} language The current language country code (e.g en-CA) 33 | */ 34 | function setLanguage(language) { 35 | if (isLanguageSupported(language)) 36 | currentLanguage = language; 37 | else 38 | currentLanguage = 'en'; 39 | } 40 | 41 | /** 42 | * Gets current language. 43 | * 44 | * @method getLanguage 45 | * @return {String} The current language country code (e.g en-US) 46 | */ 47 | function getLanguage() { 48 | return currentLanguage; 49 | } 50 | 51 | /** 52 | * Translates the given id using current language. 53 | * 54 | * @method translate 55 | * @param {String} id The id of the translation 56 | * @param {Object} [parameters] Parameters with for each parameter the key as the placeholder to replace and the 57 | * value as the placeholder substitution string 58 | * @return {String} The translated string 59 | */ 60 | function translate(id, parameters) { 61 | var translatedText = (oplI18nTranslations[currentLanguage] && oplI18nTranslations[currentLanguage][id]) || id; 62 | 63 | // Translation does not exist 64 | // Use english language as default 65 | if (translatedText === id) 66 | translatedText = oplI18nTranslations['en'][id] || id; 67 | 68 | // Parameters 69 | if (parameters) { 70 | var reg = new RegExp(Object.keys(parameters).join('|'), 'gi'); 71 | translatedText = translatedText.replace(reg, function(matched) { 72 | return parameters[matched]; 73 | }); 74 | } 75 | 76 | return translatedText; 77 | } 78 | 79 | return { 80 | translate: translate, 81 | isLanguageSupported: isLanguageSupported, 82 | setLanguage: setLanguage, 83 | getLanguage: getLanguage 84 | }; 85 | 86 | } 87 | 88 | app.service('oplI18nService', oplI18nService); 89 | oplI18nService.$inject = ['oplI18nTranslations']; 90 | 91 | })(angular, angular.module('ov.player')); 92 | -------------------------------------------------------------------------------- /src/components/shared/i18n/i18n.service.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | window.assert = chai.assert; 4 | 5 | describe('oplI18nService', function() { 6 | var oplI18nService; 7 | var expectedTranslations; 8 | 9 | // Mocks 10 | beforeEach(function() { 11 | expectedTranslations = { 12 | en: {}, 13 | fr: {} 14 | }; 15 | module('ov.player', function($provide) { 16 | 17 | // Mock players 18 | $provide.constant('oplI18nTranslations', expectedTranslations); 19 | 20 | }); 21 | }); 22 | 23 | // Dependencies injections 24 | beforeEach(inject(function(_oplI18nService_) { 25 | oplI18nService = _oplI18nService_; 26 | })); 27 | 28 | describe('isLanguageSupported', function() { 29 | 30 | it('should indicate if a language is supported or not', function() { 31 | assert.ok( 32 | oplI18nService.isLanguageSupported(Object.keys(expectedTranslations)[0]), 33 | 'Expected language support' 34 | ); 35 | assert.notOk(oplI18nService.isLanguageSupported('not supported language'), 'Unexpected language support'); 36 | }); 37 | 38 | }); 39 | 40 | describe('setLanguage', function() { 41 | 42 | it('should set a different language', function() { 43 | oplI18nService.setLanguage('en'); 44 | assert.equal(oplI18nService.getLanguage(), 'en', 'Expected "en" language'); 45 | oplI18nService.setLanguage('fr'); 46 | assert.equal(oplI18nService.getLanguage(), 'fr', 'Expected "fr" language'); 47 | }); 48 | 49 | it('should set language to "en" if specified language is not supported', function() { 50 | oplI18nService.setLanguage('not supported language'); 51 | assert.equal(oplI18nService.getLanguage(), 'en', 'Expected "en" language'); 52 | }); 53 | 54 | }); 55 | 56 | describe('translate', function() { 57 | 58 | it('should translate a string using current language', function() { 59 | expectedTranslations.en.TRANSLATION_ID = 'English'; 60 | expectedTranslations.fr.TRANSLATION_ID = 'Français'; 61 | 62 | oplI18nService.setLanguage('en'); 63 | assert.equal( 64 | oplI18nService.translate('TRANSLATION_ID'), 65 | expectedTranslations.en.TRANSLATION_ID, 66 | 'Wrong english translation' 67 | ); 68 | oplI18nService.setLanguage('fr'); 69 | assert.equal( 70 | oplI18nService.translate('TRANSLATION_ID'), 71 | expectedTranslations.fr.TRANSLATION_ID, 72 | 'Wrong french translation' 73 | ); 74 | }); 75 | 76 | it('should translate string in english if no translation found for the curent language', function() { 77 | expectedTranslations.en.TRANSLATION_ID = 'English'; 78 | oplI18nService.setLanguage('fr'); 79 | assert.equal( 80 | oplI18nService.translate('TRANSLATION_ID'), 81 | expectedTranslations.en.TRANSLATION_ID, 82 | 'Wrong translation' 83 | ); 84 | }); 85 | 86 | it('should not translate string if no translation found', function() { 87 | var expectedTranslation = 'wrong translation id'; 88 | assert.equal(oplI18nService.translate(expectedTranslation), expectedTranslation, 'Wrong translation'); 89 | }); 90 | 91 | it('should replace specified placeholders by associated values in the translated string', function() { 92 | var expectedParameters = { 93 | '%placeholder%': 'Substitution text' 94 | }; 95 | expectedTranslations.en.TRANSLATION_ID = 'Text to replace: %placeholder%'; 96 | oplI18nService.setLanguage('en'); 97 | assert.equal( 98 | oplI18nService.translate('TRANSLATION_ID', expectedParameters), 99 | expectedTranslations.en.TRANSLATION_ID.replace('%placeholder%', expectedParameters['%placeholder%']), 100 | 'Wrong translation' 101 | ); 102 | }); 103 | 104 | }); 105 | 106 | }); 107 | -------------------------------------------------------------------------------- /src/components/shared/millisecondsToTime.filter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @module ov.player 5 | */ 6 | 7 | (function(app) { 8 | 9 | /** 10 | * Creates a filter to convert a time in milliseconds to an hours:minutes:seconds format. 11 | * 12 | * e.g. 13 | * {{60000 | oplMillisecondsToTime}} // 01:00 14 | * {{3600000 | oplMillisecondsToTime}} // 01:00:00 15 | * 16 | * @class oplMillisecondsToTime 17 | */ 18 | function oplMillisecondsToTime() { 19 | return function(time) { 20 | if (time < 0 || isNaN(time)) 21 | return ''; 22 | 23 | time = parseInt(time); 24 | 25 | var seconds = parseInt((time / 1000) % 60); 26 | var minutes = parseInt((time / (60000)) % 60); 27 | var hours = parseInt((time / (3600000)) % 24); 28 | 29 | hours = (hours < 10) ? '0' + hours : hours; 30 | minutes = (minutes < 10) ? '0' + minutes : minutes; 31 | seconds = (seconds < 10) ? '0' + seconds : seconds; 32 | 33 | return ((hours !== '00') ? hours + ':' : '') + minutes + ':' + seconds; 34 | }; 35 | } 36 | 37 | app.filter('oplMillisecondsToTime', oplMillisecondsToTime); 38 | 39 | })(angular.module('ov.player')); 40 | -------------------------------------------------------------------------------- /src/components/shared/millisecondsToTime.filter.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | window.assert = chai.assert; 4 | 5 | describe('oplMillisecondsToTimeFilter', function() { 6 | var millisecondsToTimeFilter; 7 | var $filter; 8 | 9 | // Load module player 10 | beforeEach(module('ov.player')); 11 | 12 | // Dependencies injections 13 | beforeEach(inject(function(_$filter_) { 14 | $filter = _$filter_; 15 | })); 16 | 17 | // Initializes tests 18 | beforeEach(function() { 19 | millisecondsToTimeFilter = $filter('oplMillisecondsToTime'); 20 | }); 21 | 22 | it('should return an empty String if time < 0', function() { 23 | var emptyTime = millisecondsToTimeFilter(-1); 24 | assert.notOk(emptyTime, 'Expected time to be empty'); 25 | assert.isString(emptyTime, 'Expected time to be String'); 26 | }); 27 | 28 | it('should return an empty String if time is undefined', function() { 29 | var emptyTime = millisecondsToTimeFilter(undefined); 30 | assert.notOk(emptyTime, 'Expected time to be empty'); 31 | assert.isString(emptyTime, 'Expected time to be String'); 32 | }); 33 | 34 | it('should be able to convert milliseconds to hh:mm:ss', function() { 35 | var time = millisecondsToTimeFilter(8804555); 36 | assert.equal(time, '02:26:44', 'Wrong time'); 37 | }); 38 | 39 | it('should be able to convert milliseconds to mm:ss while no hours', function() { 40 | var time = millisecondsToTimeFilter(884555); 41 | assert.equal(time, '14:44', 'Wrong time'); 42 | }); 43 | 44 | it('should be able to convert milliseconds to 00:ss while no hours and no minutes', function() { 45 | var time = millisecondsToTimeFilter(5500); 46 | assert.equal(time, '00:05', 'Wrong time'); 47 | }); 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /src/components/shared/scroller/scroller.component.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @module ov.player 5 | */ 6 | 7 | /** 8 | * Creates a new AngularJS component as an opl-scroller HTML element to scroll a content. 9 | * 10 | * opl-scroller is composed of a container, the transcluded content to scroll and a scroll bar. 11 | * 12 | * Scroller value must be between 0 and 100. 13 | * 14 | * Attributes are: 15 | * - [String] **opl-id** The unique id of the scrollable content. 16 | * - [Number] **opl-step** The step to use when scrolling using keyboard (Default to 10). 17 | * - [Boolean] **opl-no-sequential-focus** true to set scrollbar tabindex to -1, false to set scrollbar tabindex to 0 18 | * - [Boolean] **opl-deactivated** "true" to deactivate the scroller 19 | * - [String] **opl-orientation** The scrollbar orientation, either "horizontal" or "vertical" 20 | * - [Function] **opl-on-touch** The function to call when scroll is manipulated by the user 21 | * - [Function] **opl-on-ready** The function to call when the scroller is ready 22 | * 23 | * @example 24 | * var value = 42; 25 | * var deactivated = false; 26 | * 27 | * var handleScrollTouch = function() { 28 | * console.log('Scroller manually updated'); 29 | * }; 30 | * 31 | * var handleOnReady = function() { 32 | * console.log('Scroller ready'); 33 | * }; 34 | * 35 | *