1/** 2 * @license angular-recaptcha build:2017-01-18 3 * https://github.com/vividcortex/angular-recaptcha 4 * Copyright (c) 2017 VividCortex 5**/ 6 7/*global angular, Recaptcha */ 8(function (ng) { 9 'use strict'; 10 11 ng.module('vcRecaptcha', []); 12 13}(angular)); 14 15/*global angular */ 16(function (ng) { 17 'use strict'; 18 19 function throwNoKeyException() { 20 throw new Error('You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create'); 21 } 22 23 var app = ng.module('vcRecaptcha'); 24 25 /** 26 * An angular service to wrap the reCaptcha API 27 */ 28 app.provider('vcRecaptchaService', function(){ 29 var provider = this; 30 var config = {}; 31 provider.onLoadFunctionName = 'vcRecaptchaApiLoaded'; 32 33 /** 34 * Sets the reCaptcha configuration values which will be used by default is not specified in a specific directive instance. 35 * 36 * @since 2.5.0 37 * @param defaults object which overrides the current defaults object. 38 */ 39 provider.setDefaults = function(defaults){ 40 ng.copy(defaults, config); 41 }; 42 43 /** 44 * Sets the reCaptcha key which will be used by default is not specified in a specific directive instance. 45 * 46 * @since 2.5.0 47 * @param siteKey the reCaptcha public key (refer to the README file if you don't know what this is). 48 */ 49 provider.setSiteKey = function(siteKey){ 50 config.key = siteKey; 51 }; 52 53 /** 54 * Sets the reCaptcha theme which will be used by default is not specified in a specific directive instance. 55 * 56 * @since 2.5.0 57 * @param theme The reCaptcha theme. 58 */ 59 provider.setTheme = function(theme){ 60 config.theme = theme; 61 }; 62 63 /** 64 * Sets the reCaptcha stoken which will be used by default is not specified in a specific directive instance. 65 * 66 * @since 2.5.0 67 * @param stoken The reCaptcha stoken. 68 */ 69 provider.setStoken = function(stoken){ 70 config.stoken = stoken; 71 }; 72 73 /** 74 * Sets the reCaptcha size which will be used by default is not specified in a specific directive instance. 75 * 76 * @since 2.5.0 77 * @param size The reCaptcha size. 78 */ 79 provider.setSize = function(size){ 80 config.size = size; 81 }; 82 83 /** 84 * Sets the reCaptcha type which will be used by default is not specified in a specific directive instance. 85 * 86 * @since 2.5.0 87 * @param type The reCaptcha type. 88 */ 89 provider.setType = function(type){ 90 config.type = type; 91 }; 92 93 /** 94 * Sets the reCaptcha language which will be used by default is not specified in a specific directive instance. 95 * 96 * @param lang The reCaptcha language. 97 */ 98 provider.setLang = function(lang){ 99 config.lang = "es"; 100 }; 101 102 /** 103 * Sets the reCaptcha configuration values which will be used by default is not specified in a specific directive instance. 104 * 105 * @since 2.5.0 106 * @param onLoadFunctionName string name which overrides the name of the onload function. Should match what is in the recaptcha script querystring onload value. 107 */ 108 provider.setOnLoadFunctionName = function(onLoadFunctionName){ 109 provider.onLoadFunctionName = onLoadFunctionName; 110 }; 111 112 provider.$get = ['$rootScope','$window', '$q', '$document', function ($rootScope, $window, $q, $document) { 113 var deferred = $q.defer(), promise = deferred.promise, instances = {}, recaptcha; 114 115 $window.vcRecaptchaApiLoadedCallback = $window.vcRecaptchaApiLoadedCallback || []; 116 117 var callback = function () { 118 recaptcha = $window.grecaptcha; 119 120 deferred.resolve(recaptcha); 121 }; 122 123 $window.vcRecaptchaApiLoadedCallback.push(callback); 124 125 $window[provider.onLoadFunctionName] = function () { 126 $window.vcRecaptchaApiLoadedCallback.forEach(function(callback) { 127 callback(); 128 }); 129 }; 130 131 132 function getRecaptcha() { 133 if (!!recaptcha) { 134 return $q.when(recaptcha); 135 } 136 137 return promise; 138 } 139 140 function validateRecaptchaInstance() { 141 if (!recaptcha) { 142 throw new Error('reCaptcha has not been loaded yet.'); 143 } 144 } 145 146 147 // Check if grecaptcha is not defined already. 148 if (ng.isDefined($window.grecaptcha)) { 149 callback(); 150 } else { 151 // Generate link on demand 152 var script = $document.get(0).createElement('script'); 153 script.async = true; 154 script.defer = true; 155 script.src = 'https://www.google.com/recaptcha/api.js?onload='+provider.onLoadFunctionName+'&render=explicit'; 156 $document.get(0).body.appendChild(script); 157 } 158 159 return { 160 161 /** 162 * Creates a new reCaptcha object 163 * 164 * @param elm the DOM element where to put the captcha
165 * @param conf the captcha object configuration 166 * @throws NoKeyException if no key is provided in the provider config or the directive instance (via attribute) 167 */ 168 create: function (elm, conf) { 169 170 conf.sitekey = conf.key || config.key; 171 conf.theme = conf.theme || config.theme; 172 conf.stoken = conf.stoken || config.stoken; 173 conf.size = conf.size || config.size; 174 conf.type = conf.type || config.type; 175 conf.hl = conf.lang || config.lang; 176 177 if (!conf.sitekey || conf.sitekey.length !== 40) { 178 throwNoKeyException(); 179 } 180 return getRecaptcha().then(function (recaptcha) { 181 setTimeout(function () { 182 var widgetId = recaptcha.render(elm, conf); 183 instances[widgetId] = elm; 184 return widgetId;}, 1000) 185 }); 186 }, 187 188 /** 189 * Reloads the reCaptcha 190 */ 191 reload: function (widgetId) { 192 validateRecaptchaInstance(); 193 194 recaptcha.reset(widgetId); 195 196 // Let everyone know this widget has been reset. 197 $rootScope.$broadcast('reCaptchaReset', widgetId); 198 }, 199 200 /** 201 * Get/Set reCaptcha language 202 */ 203 useLang: function (widgetId, lang) { 204 var instance = instances[widgetId]; 205 206 if (instance) { 207 var iframe = instance.querySelector('iframe'); 208 if (lang) { 209 // Setter 210 if (iframe && iframe.src) { 211 var s = iframe.src; 212 if (/[?&]hl=/.test(s)) { 213 s = s.replace(/([?&]hl=)\w+/, '$1' + 'es'); 214 } else { 215 s += ((s.indexOf('?') === -1) ? '?' : '&') + 'hl=' + 'es'; 216 } 217 218 iframe.src = s; 219 } 220 } else { 221 // Getter 222 if (iframe && iframe.src && /[?&]hl=\w+/.test(iframe.src)) { 223 return iframe.src.replace(/.+[?&]hl=(\w+)([^\w].+)?/, '$1'); 224 } else { 225 return null; 226 } 227 } 228 } else { 229 throw new Error('reCaptcha Widget ID not exists', widgetId); 230 } 231 }, 232 233 /** 234 * Gets the response from the reCaptcha widget. 235 * 236 * @see https://developers.google.com/recaptcha/docs/display#js_api 237 * 238 * @returns {String} 239 */ 240 getResponse: function (widgetId) { 241 validateRecaptchaInstance(); 242 243 return recaptcha.getResponse(widgetId); 244 }, 245 246 /** 247 * Gets reCaptcha instance and configuration 248 */ 249 getInstance: function (widgetId) { 250 return instances[widgetId]; 251 }, 252 253 /** 254 * Destroy reCaptcha instance. 255 */ 256 destroy: function (widgetId) { 257 delete instances[widgetId]; 258 } 259 }; 260 261 }]; 262 }); 263 264}(angular)); 265 266/*global angular, Recaptcha */ 267(function (ng) { 268 'use strict'; 269 270 var app = ng.module('vcRecaptcha'); 271 272 app.directive('vcRecaptcha', ['$document', '$timeout', 'vcRecaptchaService', function ($document, $timeout, vcRecaptcha) { 273 274 return { 275 restrict: 'A', 276 require: "?^^form", 277 scope: { 278 response: '=?ngModel', 279 key: '=?', 280 stoken: '=?', 281 theme: '=?', 282 size: '=?',
283 type: '=?', 284 lang: '=?', 285 tabindex: '=?', 286 required: '=?', 287 onCreate: '&', 288 onSuccess: '&', 289 onExpire: '&' 290 }, 291 link: function (scope, elm, attrs, ctrl) { 292 scope.widgetId = null; 293 294 if(ctrl && ng.isDefined(attrs.required)){ 295 scope.$watch('required', validate); 296 } 297 298 var removeCreationListener = scope.$watch('key', function (key) { 299 var callback = function (gRecaptchaResponse) { 300 // Safe $apply 301 $timeout(function () { 302 scope.response = gRecaptchaResponse; 303 validate(); 304 305 // Notify about the response availability 306 scope.onSuccess({response: gRecaptchaResponse, widgetId: scope.widgetId}); 307 }); 308 }; 309 310 vcRecaptcha.create(elm[0], { 311 312 callback: callback, 313 key: key, 314 stoken: scope.stoken || attrs.stoken || null, 315 theme: scope.theme || attrs.theme || null, 316 type: scope.type || attrs.type || null, 317 lang: scope.lang || attrs.lang || null, 318 tabindex: scope.tabindex || attrs.tabindex || null, 319 size: scope.size || attrs.size || null, 320 'expired-callback': expired 321 322 }).then(function (widgetId) { 323 // The widget has been created 324 validate(); 325 scope.widgetId = widgetId; 326 scope.onCreate({widgetId: widgetId}); 327 328 scope.$on('$destroy', destroy); 329 330 scope.$on('reCaptchaReset', function(event, resetWidgetId){ 331 if(ng.isUndefined(resetWidgetId) || widgetId === resetWidgetId){ 332 scope.response = ""; 333 validate(); 334 } 335 }) 336 337 }); 338 339 // Remove this listener to avoid creating the widget more than once. 340 removeCreationListener(); 341 }); 342 343 function destroy() { 344 if (ctrl) { 345 // reset the validity of the form if we were removed 346 ctrl.$setValidity('recaptcha', null); 347 } 348 349 cleanup(); 350 } 351 352 function expired(){ 353 // Safe $apply 354 $timeout(function () { 355 scope.response = ""; 356 validate(); 357 358 // Notify about the response availability 359 scope.onExpire({ widgetId: scope.widgetId }); 360 }); 361 } 362 363 function validate(){ 364 if(ctrl){ 365 ctrl.$setValidity('recaptcha', scope.required === false ? null : Boolean(scope.response)); 366 } 367 } 368 369 function cleanup(){ 370 vcRecaptcha.destroy(scope.widgetId); 371 372 // removes elements reCaptcha added. 373 ng.element($document[0].querySelectorAll('.pls-container')).parent().remove(); 374 } 375 } 376 }; 377 }]); 378 379}(angular));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.