Skip to content
This repository was archived by the owner on Aug 17, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ node_js:
before_script:
- npm install -g grunt-cli bower
- bower install
- "export CHROME_BIN=chromium-browser"
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"

script:
- grunt karma:ci

after_script:
- grunt coverage
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports = function (grunt) {
},
ci: {
configFile: 'karma.conf.js',
browsers: ['Chrome', 'Firefox', 'FirefoxNightly'],
browsers: ['Chrome_travis_ci', 'Firefox', 'FirefoxNightly'],
singleRun: true
}
},
Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,12 @@ You can optionally pass a __theme__ the captcha should use, as an html attribute
size="---- compact or normal ----"
type="'---- audio or image ----'"
key="'---- YOUR PUBLIC KEY GOES HERE ----'"
lang="---- language code ----"
></div>
```

**Language Codes**: https://developers.google.com/recaptcha/docs/language

In this case we are specifying that the captcha should use the theme named _light_.

Listeners
Expand All @@ -153,6 +156,7 @@ There are three listeners you can use with the directive, `on-create`, `on-succe
on-create="setWidgetId(widgetId)"
on-success="setResponse(response)"
on-expire="cbExpiration()"
lang=""
></div>
```

Expand Down Expand Up @@ -205,19 +209,24 @@ myApp.config(function(vcRecaptchaServiceProvider){
vcRecaptchaServiceProvider.setStoken('--- YOUR GENERATED SECURE TOKEN ---')
vcRecaptchaServiceProvider.setSize('---- compact or normal ----')
vcRecaptchaServiceProvider.setType('---- audio or image ----')
vcRecaptchaServiceProvider.setLang('---- language code ----')
});
```

**Language Codes**: https://developers.google.com/recaptcha/docs/language

You can also set all of the values at once.

```javascript
myApp.config(function(vcRecaptchaServiceProvider){
vcRecaptchaServiceProvider.setDefaults({
key: '---- YOUR PUBLIC KEY GOES HERE ----',
theme: '---- light or dark ----',
stoken: '--- YOUR GENERATED SECURE TOKEN ---',
size: '---- compact or normal ----',
type: '---- audio or image ----'
key: '---- YOUR PUBLIC KEY GOES HERE ----',
theme: '---- light or dark ----',
stoken: '--- YOUR GENERATED SECURE TOKEN ---',
size: '---- compact or normal ----',
type: '---- audio or image ----',
lang: '---- language code ----'
});
});
```
Note: any value omitted will be undefined, even if previously set.
Expand Down
6 changes: 6 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ module.exports = function (config) {
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS', 'Chrome', 'IE', 'Safari', 'Firefox', 'FirefoxNightly', 'ChromeCanary'],

customLaunchers: {
Chrome_travis_ci: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},

// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
Expand Down
43 changes: 25 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
"author": "VividCortex",
"license": "MIT",
"homepage": "https://github.com/vividcortex/angular-recaptcha",
"contributors": [
{
"name" : "Eduardo Daniel Cuomo",
"email" : "reduardo7@gmail.com",
"url" : "https://github.com/reduardo7/angular-recaptcha"
}
],
"main": "release/angular-recaptcha.js",
"repository": {
"type": "git",
Expand All @@ -14,23 +21,23 @@
"test": "grunt test"
},
"devDependencies": {
"bower": "^1.3.3",
"grunt": "~0.4.2",
"grunt-bump": "0.0.13",
"grunt-cli": "~0.1.11",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.4.0",
"grunt-karma": "^0.10.1",
"grunt-karma-coveralls": "^2.5.3",
"jasmine-core": "^2.2.0",
"karma": "^0.12.31",
"karma-chrome-launcher": "^0.1.7",
"karma-coverage": "^0.2.7",
"karma-firefox-launcher": "^0.1.4",
"karma-ie-launcher": "^0.1.5",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4",
"karma-safari-launcher": "^0.1.1"
"bower": "^1.8.0",
"grunt": "^1.0.1",
"grunt-bump": "^0.8.0",
"grunt-cli": "^1.2.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^2.0.0",
"grunt-karma": "^2.0.0",
"grunt-karma-coveralls": "^2.5.4",
"jasmine-core": "^2.5.2",
"karma": "^1.3.0",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^1.0.0",
"karma-ie-launcher": "^1.0.0",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-safari-launcher": "^1.0.0"
}
}
4 changes: 4 additions & 0 deletions src/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
theme: '=?',
size: '=?',
type: '=?',
lang: '=?',
tabindex: '=?',
required: '=?',
onCreate: '&',
Expand Down Expand Up @@ -48,6 +49,7 @@
stoken: scope.stoken || attrs.stoken || null,
theme: scope.theme || attrs.theme || null,
type: scope.type || attrs.type || null,
lang: scope.lang || attrs.lang || null,
tabindex: scope.tabindex || attrs.tabindex || null,
size: scope.size || attrs.size || null,
'expired-callback': expired
Expand Down Expand Up @@ -100,6 +102,8 @@
}

function cleanup(){
vcRecaptcha.destroy(scope.widgetId);

// removes elements reCaptcha added.
ng.element($document[0].querySelectorAll('.pls-container')).parent().remove();
}
Expand Down
64 changes: 61 additions & 3 deletions src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
config.type = type;
};

/**
* Sets the reCaptcha language which will be used by default is not specified in a specific directive instance.
*
* @param lang The reCaptcha language.
*/
provider.setLang = function(lang){
config.lang = lang;
};

/**
* Sets the reCaptcha configuration values which will be used by default is not specified in a specific directive instance.
*
Expand All @@ -87,7 +96,7 @@
};

provider.$get = ['$rootScope','$window', '$q', function ($rootScope, $window, $q) {
var deferred = $q.defer(), promise = deferred.promise, recaptcha;
var deferred = $q.defer(), promise = deferred.promise, instances = {}, recaptcha;

$window.vcRecaptchaApiLoadedCallback = $window.vcRecaptchaApiLoadedCallback || [];

Expand Down Expand Up @@ -142,12 +151,15 @@
conf.stoken = conf.stoken || config.stoken;
conf.size = conf.size || config.size;
conf.type = conf.type || config.type;
conf.hl = conf.lang || config.lang;

if (!conf.sitekey || conf.sitekey.length !== 40) {
throwNoKeyException();
}
return getRecaptcha().then(function (recaptcha) {
return recaptcha.render(elm, conf);
var widgetId = recaptcha.render(elm, conf);
instances[widgetId] = elm;
return widgetId;
});
},

Expand All @@ -157,13 +169,45 @@
reload: function (widgetId) {
validateRecaptchaInstance();

// $log.info('Reloading captcha');
recaptcha.reset(widgetId);

// Let everyone know this widget has been reset.
$rootScope.$broadcast('reCaptchaReset', widgetId);
},

/**
* Get/Set reCaptcha language
*/
useLang: function (widgetId, lang) {
var instance = instances[widgetId];

if (instance) {
var iframe = instance.querySelector('iframe');
if (lang) {
// Setter
if (iframe && iframe.src) {
var s = iframe.src;
if (/[?&]hl=/.test(s)) {
s = s.replace(/([?&]hl=)\w+/, '$1' + lang);
} else {
s += ((s.indexOf('?') === -1) ? '?' : '&') + 'hl=' + lang;
}

iframe.src = s;
}
} else {
// Getter
if (iframe && iframe.src && /[?&]hl=\w+/.test(iframe.src)) {
return iframe.src.replace(/.+[?&]hl=(\w+)([^\w].+)?/, '$1');
} else {
return null;
}
}
} else {
throw new Error('reCaptcha Widget ID not exists', widgetId);
}
},

/**
* Gets the response from the reCaptcha widget.
*
Expand All @@ -175,6 +219,20 @@
validateRecaptchaInstance();

return recaptcha.getResponse(widgetId);
},

/**
* Gets reCaptcha instance and configuration
*/
getInstance: function (widgetId) {
return instances[widgetId];
},

/**
* Destroy reCaptcha instance.
*/
destroy: function (widgetId) {
delete instances[widgetId];
}
};

Expand Down
27 changes: 27 additions & 0 deletions tests/directive_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,32 @@ describe('directive: vcRecaptcha', function () {
widgetId: undefined
});
});

it('the widget should be using the setted language', function () {
var element = angular.element('<form name="form">' +
'<input type="text" ng-model="something" />' +
'<div vc-recaptcha key="key" on-create="onCreate()" lang="es" on-success="onSuccess({response: response, widgetId: id})"/>' +
'</form>'),

_fakeCreate = function (element, config) {
config.callback(config.lang);
return {
then: function (cb) {
cb();
}
};
};

spyOn(vcRecaptchaService, 'create').and.callFake(_fakeCreate);

$compile(element)($scope);
$scope.$digest();
$timeout.flush();

expect($scope.onSuccess).toHaveBeenCalledWith({
response: 'es',
widgetId: undefined
});
});
});
});
24 changes: 23 additions & 1 deletion tests/service_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ describe('service', function () {
theme: undefined,
stoken: undefined,
size: undefined,
type: undefined
type: undefined,
hl: undefined
};

$window.vcRecaptchaApiLoaded();
Expand Down Expand Up @@ -63,4 +64,25 @@ describe('service', function () {
expect($window.grecaptcha.getResponse).toHaveBeenCalledWith(_widgetId);
});
});

describe('useLang', function () {
it('should call useLang', inject(function ($rootScope) {
var _element = angular.element('<div><iframe src="http://localhost?hl=fr"></iframe></div>')[0],
_key = '1234567890123456789012345678901234567890';

$window.vcRecaptchaApiLoaded();

vcRecaptchaService.create(_element, {
key: _key
}).then(function (widgetId) {
var instance = vcRecaptchaService.getInstance(widgetId);
expect(instance).toEqual(_element);

vcRecaptchaService.useLang(widgetId, 'es');
expect(vcRecaptchaService.useLang(widgetId)).toEqual('es');
})

$rootScope.$digest();
}));
});
});