Is it me or GoogleTagManager do not seem to accept base64 encoded pictures?
Exemple with the very basic code below with a very basic image.
I get the following error :
- Type : JavaScript Too Long"
- Description :
"The JavaScript in your Arbitrary HTML tag has too many contiguous non-whitespace characters (e.g. an array literal '[1,2,..]' that is too long). Try inserting spaces between statements to allow compilation (e.g. change '[1,2,...]' to '[1, 2, ...]')."
Is there no way to implement this in GTM, beside putting the js somewhere else than directly into GTM?
Best,
J.
<script type="text/javascript">
var myurl = "http://wwww.toto.com";
var myimg = "data:image/jpeg;base64,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";
$("#beta-ad").empty();
$('<div/>', { id: "1" }).insertBefore($("#beta-ad"));
$("#1").append('<img src="' + myimg + '" style="display:inline; width: auto;" ></img>')
</script>
I think this is by design. But the workaround proposed by #Matus works.
To get around the issue of having to generate JS for a very long base base 64 encoded string I wrote a utility function, splitting the string into chunks of 150 (which GTM accepts), and generating the JS concatenation code.
You can then drop this code into your GTM tag, and reference the base64 variable.
function splitString(string, size, multiline) {
var matchAllToken = (multiline == true) ? '[^]' : '.';
var re = new RegExp(matchAllToken + '{1,' + size + '}', 'g');
var responses = string.match(re);
var value = "var base64='';";
responses.forEach(response => {
value += "base64+='" + response + "';";
});
return value;
}
var base64 = 'eyJ3aWRnZXRfc2.... etc';
var gtmString = splitString(base64, 150, true);
console.log(gtmString);
http://jsfiddle.net/azqpdwxg/2/
I'm attempting to parse a Javscript object online using nodejs.
This file for example: http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU
This is not JSON, and is regular JavaScript. I have managed to parse out the JavaScript object using:
/* Data is the JS file above */
var j = data.substring(data.indexOf('{'), data.indexOf('}') + 1);
But, how do I parse that so I can read it as an object? JSON.parse doesn't work because its not JSON formatted.
Edit
As the challenge key is what I require, I ended up solving it with substring and indexOf:
var start = data.indexOf('\'');
var end = data.substring(start + 1).indexOf('\'');
var challenge = data.substring(start, (start + end) + 1);
But I'd still like to know a solution to the origional problem. And yes, I could use "'" but in this project we stuck to using single quotes and I'm a stickler for making sure everything is in line with the style guide. Silly I know, just a habbit.
well the simplest way is the following for this particular issue.
var x = JSON.stringify({
challenge : '03AHJ_VuuiaIB_izO6VJ6PifXI8A8i1yBeG6biCjadtaZHk5pbxfbW5JPpEXBEay-LPdCzSOI1bQgdnjq1tQVSqzQ63hMQB1Sjlho4LdzfZKLXuK3TKZD1YPr5bIjM-dYqHIkcYpaanchXOXLkHNoj0B6_ZrUk4rZg-o790H1LMNzoPGy3qkk6suYWs1CERFjkTO_mw9puMnYQNITPzBnRS-QMilbch2d_PeM2aDGToLSQiLn8mgHwP7fUHvCcE9VGzNZNXkDC8wF-YvUCxU354VqeSa8U7KKycg',
timeout : 1800,
lang : 'en',
server : 'http://www.google.com/recaptcha/api/',
site : '6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU',
error_message : '',
programming_error : '',
is_incorrect : false,
rtl : false,
t1 : 'Ly93d3cuZ29vZ2xlLmNvbS9qcy90aC9PejNvSUJCSlYxanlWSi13QTFqRndDd3dhbk5QVTh2TGd6SWVaNGc2TkxnLmpz',
t2 : '',
t3 : 'V3h0N3Vzd1cvWFR1d08yYmtyZG5HdDFoS1oyenNXMzBpS0dkRXVHUXc4anVBemtvemM2R1VhVDlPSmk0M0lRSWtMVVFUZ1JIWHlmUjE0VlBKQldOUVJuWG4ydXVzdjhJY2JZbHFCNGgxUGwvUzlzbE1reEpMcVcrbFRiS2JQWE9ZUXo5M3EwVDVPTFB4WVdHcTkzK0RuTXpjUTRtV0VhTUxOcDhqa2M2MitTT2w4dHVudHJ6NnlYdWdOVzFLMmlZOG8zOG5uUGNGZnp5ODcyZXZwTlIzRytJdkQyVFdsZFNzOXJ1amtDSkpRamtvQUdIYVpnRDBrODJxREdMSjhqRElQY1BqbTNUcno3TFQ4bG5jZ1pjbUM3NFpXdHlmVWhmYnNXRDNkMlBuaFdvM1lyUUp4Y1R5Z2F3elR2K3hpLzFyeisydU9SaTVJVk9MZFdpekQ3Y0NUQ0NDRlhVdDg1MElZalp4MkNYbkVWNkFmUDZ1UDNTOXhvaWxtaGdzWkg0OTZyQVFTai81RWdGelpLcFNVQnVtbGJGaFVLTWRDbHlGZ1orbGdRSVVubWk0WURTc2JMd1FaZkRhZlBZcjhJY0pyOWZSaU1leGpuMU9TNWk5UkZ2M0hLTG5jQzh3Y3plVzVKZjluYlZOWWdVY1l5U3FadmxOamF0Q3ozeXphNDhtazZwNHlIYUtWN1RvSGNvKzArWGpncm01YVd5cXpoYnRWb3Z5R2loUDNZeWswQmwwbXo0eEJUVm9HUjMzcGdtRHNYaFZRZ3lxRGJ3Wjl4YWxoN3NDQ21MVUVVOHZWWUtucGltNXpjSkU5RUlTaTk3NDBpcENxVGMrdytvRXJWTzU2VTczckZmM0FDbjlaeDFYbklueTF5SnU1TXBMaXAwSk5LSHB2R0lLb0poVjFnZ2M4bnRmNW1xQXJpWHByc1hJTk9pT20rdWIxZjFiWVBnRFJ1T3U2bjhwQm4wd2pqSStXck1ZU0xCMzZabW1taEZreWhEWTRBa0RzTWVWTG9ydzZSanJ2WURsc3NxY2wxZTAzT1k1aXl5T0o5dVVsR09DcDhaNHFoeFdYY0JiWk5ONndXTndXTnJGOGxkQkI3cHBhUVUySTFBZTk1ZXVRWHdRQjB4SWhqd3ZZQ2ZQU21DRFByTzhPYm9rK1BkeU5rTXhXODZxSnNWVUliU3U2ekZIYWdaV2xoaEx0Y1B6UFYrNXNvZVZXeVVpUXZKL2orVHNiYXJ3OFN4cDRMYTJvYWhFSUdybTlvaklTZHUxODhCS1ByakE5YWU5c2hITTRGczBreFU3a0tVbDI5d3JnT2NpcW1vVlptOTdsZnU1cWxGSXRTajdoVGlUZlV2V2s4NGEyOVpDcG9Xek91ZTZ1eFdFalJuMTVBb0FaTlFRWnhhQ3RkRlJJWTZ4U2p6TWRMNG9qZDFXbXhZNkFrK1I0Z3FkclhWQ090SEc0cnZITVN5ZWJCZ0pqcWIwWDJ4aTZNOVJTRlAwMUc1OTRvQ0hLb1h2TWcvTUxneEZtaUdGRkhPNnpNN2F1djl2bm1nb1IzbXF0Y1J3U2ZBaDNoQmxlWjV6dVg4ejdUQldhaUNDWHNuTEpnY1lxendaYTFZQWNFbjB1aWhtb0lwYzJmYXBHa0xPbWV2MlgyejJWeWJzdThpM3A2MlgyOXFxZklPLy9GdGdDZURsN0VXOTM4YzhRbEgwa1hqeUNhRStmU2dNVkl3MUZyMU9XVFNReVJXSVA4UXFyOTJVM1pHYm83cmtGeFU3dXBpWWU4eG1qSkt4R0FRMEdhY2J3aXdnL3RCQ2NsZHdZQ3lGNTdkRzY3T0p0SzdSNkdoZm1VQWlvOEF0UGI5WU1UYllJOWlhTytRK3FCS1NrakxWQlVWY1R3d2gxRlAvUkZWbm5XRmNrazdLUjVreTh0bjFYUVB4bWM0ZytSZUtXTnBYWlVrYnllSGF6M0w0dkNjYkRBT1B0aDFrNW41WEphNmwzcFlJM29NTXU4L0p2WW1TKzlaWUtsRExncXZZOEVDUEFFd05VS3ZEV2d1SlpobzZURVFkOGF0ekFHNHFidXpudXRLYmk3SXlVUDF5cHVqMVNFSTEvOFB6NHRTZ1kwRUZwOGFhbmVtNDRJaUlSeXUxYk5hZ2JPWlZVZTJUM0V4WUZncldjNk9VcEhscGE2UWY5d2FVNDJROWovTmJHMkJ5VndUcFNNZTZPMHUxeFhXTEFWRlpuMnk2SmtHN2xSZXFCTDFnaTZoMEpncmxzeWg4U3NibGRZWU1UMlNZWndYR3dNZUhpc1IyNHlFY3BZK1l6YlZ4aTRLOWRYSFhNRDJsUGlleEJsaUVEUTZtZ2dlSUJiZThpY2FITlY4Vy82MW10dmRVaGVCZnhuSk5FVTFQcm5aQm0ram9UZ3o2T1NVanYzaXA1S3E5dkZFcllDd091WFIwaC8zSFg2bENXc1grN2hBYXdFMU5WVW9icFBnWEUwTWlmVkV3eFhnR1p4TlQ1bkt5Y1o0ZzMxSm1lSkEzZ0o1RU5Zb1ZrZHViN21wSkJDeHo2T3R5cWhSR0tIcGpURElVSFlhMGNQeUtkM0poRjdxakF3eEFwSVJBNXoyRXhnZVN4RXFZVWNzaGVzNHZvSXA2bXo3U1JTb20wZkpJeXdVSFQ3THBTY0d5L1o3ZkRtVHBLemF0cCtrRmJZYzIvS1VGQ045RWFVdHZvN0I1aWxkVlRoeHpBdWVPbHZ5djBBVkNvZndGR1dVQlBmTmZVNVdwWkMvZkN4VWNXeG92Z1F0V21yTzI1Q1pzdWN6bnBobnhSMWYrLzRzZUJyckdZdWo3Q1YxaXJRcDhDZlJ6RTJudUpkWGlscWE1YXRyWmhRM2g3d1BEVXpFcDFqK2JSUjZyZmRQZ0t4K01teEVGUjJPNlNZTGlZamIrTDRhTVRrSEMrMzBycmFyMkVGMEhKd3MxOFlKWisyVXRnMXJsL3kyWC83akhieVBvbmNQdDNobUpKbW52OEVYTWdsdmtSNDE5VW5yNGkwY0d0amhpek1zZlh4TGtXai9tNlR4S3ZLQ2Q0SnhVa21DUllZVG12ZWw2RG1ubWtBVFdkTjFEZW9VOVAvMjVWak83Y3FIY3VQNTMrRjgzTk1VYmxiVzZ4VFRUMDY3SDJOemQ5S0VvSFpMcUgveVFmMDlwOVRUakRrcXZlQkk2aUx0WEZFdmQvdW9HTm4vSmNocEFQQ1hsbkhQbTlPbGI1YjVVejZhbVVPQ0U5OWhQTGlBcS9nVUFFSk9qdkZuYjFua3pxemxaWFVRSFpLRGxPUDhLNzlPMUNHSVNNUDZWRzNOVk4xRUJnSkx5dDN3NWMwemI3TDVGZ2oyZ1J4V2ZSUHpCRkFpb2hNR0RWS0QwN0JxN1Zib3lLeWxnWFpodjdqeXRLMmVSUVI0S1pUcXZ4cXpRWE1oMm9wVWk0V1Jhdis3amdsMlpPRlhSS2g0OGp2WGZKZW04NlIyRHJHcjVvNkMyaWFsWHBRWnAwWFE0UHNucEw4cDBGMVFFWCtHK1hhMFJrWERmTkNBV0FLQkoxTm5nNW9CdVFYR0JXWFVnL0Qxd0VHdk1Ub0M5ZGJ3YkE0enBISUtBRjQvWTRzSk5xTGY5L3RVUGhXSkRBa2NyWDNuNTR0ZWo5bGpqcGlpQmVxMlBGa0lBRG1nRzlzQ2hSdHAvKzBlZjhCTkNnTGQxVk1iNVRqaXdJS0dNdXkyb0VCa2FablNVbmZpWWVrMy8zTHRsSVVrZGdkZ3NYdWFNd2piSGhJcEhOQlF4Q25acWxYcDBMM2RWdUIwMkdTS2NXcEZrV01ZVy9lTlRnNkVwYWdYN1NhVjY3amUwQm4rTUdnMjdJdXlhZ2xQVlJ0NFZObk9EblBmQmpOZjNHdWZpS3ZkNHcvdlJ4NXFxYk9tNGtLTjFKQ3VDcVAzaFBhcWZveWVpamhWS0RuVW83MEpka3gzSjk2bFpBT2N2Z1NJaVNlM2h3MmlNM1V2WlpaVnpnOVJna3FXTUIxdVVlRXZTVkdxR2hKY0VaVllNMVdxOUVxMy9sZzZmSktzMitCanUzbXdsSGV0RUgzdUF1OHlQU2g0REhYYnU2VjkrYkpJOFZXK213b0YzT2xaNzYvMUZ0Q20xZ2QxdkJBOWM3RFdaU3VuVlByTnBldXFSa3VoODBBZVFQQTQ2SjAzOEQvMFNxZ2Z3cjRUWndDT1dPWEFkanFlUWdOWEdSc05iWjVSRFRxVlJSeWZCdTl1ZUVyRlF5bkthSEJFRTNxLzhtOWZSVXJkTE5jVW83VmhQYlQzWXVCNThGMjZxQ2o4L0U4WkZNVDlxbUtMb3BxT3lPUGJhMEhwSlkvSGxoZHZib3FMYkVkaFNjYXp4OEJDWXMvOVVEZ2JCemhXVnVJbTBsRzh5bEhuVTIyM1lRa2oweDhYeUpqZ0hlalJJL3hVUlJ2OGF0MGZINi9FbXM1ZlA3VE1zb3Y0MjVZUmFjeVpZajd1OGhGLzRSVFU0SXJKVGZrRm4xMkI2Q3FxOWF5dURpcjZkOHdnVy9BbExmT2g4OGxjQVh0WlJLaStzalIxYmhPY2crTFlGZXUwS2lKbnEzM1ZXL2VCSVNXSkpFdVpmaW1DWUlFQnc4T0huN3ZiT3BxZG9Cb0JrdmZjK3hsUDdwR25rM0NDaHNHNGliWjVSS0FxZ1dleTZZb0I3V1dhNWNya3VrbWRoYTlOZVV3R29kNVRUOEp3T2Y0MUo1SE5JQStSb3ZHZy96ZkxoUVMxYm52VUNCYWZzOW1xMmVBd1k0b2R6TGNFY1lZbFo1dlJmYkVSeS9MbFpEYmR1a3ZMczVQbVhFVGkzL2lHZElkREg5Vy9iNmFVenNnUE1UZGxzNU5taVJ2blNnSGtmR2hmdUhsUGtyclZUaTVCWGgwaFVRMERxbnlLT1c5SksxNHptZFNEcVZEQ0U2cUhVak1iMDlvK1RhRjZJcjQrVERLQS9LNlplWDdWem5nc1ZrOHVzdFY0bWxXbVNlQ3IxREV5V295WUtvRitjbWxFRlJPeEgwSnRwYlU2VENwRE9GSVIyNHdOdWtxT3pGeVFxTTZsZlpMUVkyWWE4ZjBINVh4WHQzYUhTajI4RlVLcjBOZEYvOElsb3NIZnpRUzNmT2R3b3Q0K2ZRVk5ReXlYK2U0QUlVTllqaDFJSi9GTkdER3IzTWVDd2ZRbTVCVVN0QkhVc0VualJCUXFmS0hVaU9WS1FYSWpMbklQM2tRYXMwWWtFYnFWUi9zcFYwKzUveFpXbmtuTkduZTBhd25DeVhNeW1qMU05cWlackp1UlJjUTk3VVVMeU54QXorWlJwcEJ5ZjBER3ROOTNyS2RTeEJmQ3JGd1dXUHY4YXIweWxiRi9WOHdiUklSb0tET2dHZjl5MWVoaEFYSmxsSFJBaGdUSjBvOVlkUFBvT2l1bGlNVTFScnZIVk8xaVFmcW96UklaV3p4U2JSWkJYYXRhVkRVSVlKTTR6Wjdoak8rSnRNb0VDQlBUVncwYVlRZHVEUEJYcFFSM2RlbTY0eFZXZHY1Tkk2MUxwazUvdVdqN29KckRZYXh1ODR0bTU5dkIrYjB6dHpibmlyYUhMa3ZwNXFXSnFqN3p2NEVPNnhYTm5pcnVLa3AxME5GeWhLQ3ZIajB5WmhxYkF5SUlBV0YyWGxuSU1mcVZsZ1czT3A1MFhHeGxOMnI2QjJhRXBvL0ttRktKN2wvRldsakwveDlBemExMzQzUHJ2WElncm01dGt2clh3QXU1M1Y0YXp0MXdaT1pNZGNPdEZWRlRLczZwMjZhcHBHb1gzcGxzUVQ1NFdwWTVSdVdVQ2tqeHM1dVJXdjVnaG1JTGZ2WlE5MmxoVStTWko0RUQxRk54UjhRRi9hRzZzdmRNZ21icXk4Y21VOFFCaUJtbG03akNjQnIzaHE3bThIcWFoUnliYmdKbFZIWkN5bk92bTMxc1JWTXNsVkxmOXNNYnhWR0VZNHZaYm5pWGZRYlg2ejZubHRoYVgvaXNSZWdKbkxLZUFYdWdQTHdxd0RDRit0MHRSY2V2aVV1MEYzdDhtdDhIRFFGd2ZFbVk1REVYdjZRZ2doNlhTY1ZzVzRIbnVtWTg1UnVTaGxRNVNTcmg5bXVBVTdvNEdnenZRNlhMVi9zcFNSbnBxVkUzRmJQaGxKd004TVkxaFhURUpEZWFIb0hHNzNXbG4yQksrcmRQR0dNV3pUeEJjbHB1aEZPRVViSHF2Z2ZFSE1BNWc1MlVxZG5JaVNJOGtqQ240YUM3Uk51c1gzanluMnVDVmQ2dlI3TDJJMURtTU51dmtJckQwQnNGc2NhSWNTMm9sY0dBYzhXVHc1U29ZRXFnRkovOU8yU3M1dy9IY3E3bmQ5MkpKQzQwd2Z0RHRzTVJaODlLdm1HNlBCUnZJZ3lHM0k5N2tOWEh2YTdQK1Q0NjE1cTUrVzhQZXZVNEVRM0dXa0dYMUhuMTlpbmZCNUtkQkphTGJMeEl1WTYyaWNWbU0rUUlpMmNyVmZ2YXN6SnJPSDBaN0hRaHJqcTVWdWFiY2tnSUpqQjZLUXVPSGVDQk95aVZobjQrUGJxQWl4Sk5DMDZuUDVLRzRTSkc1V0dTMHpxUmYyV2VRc0I3OFJPT1hpVnpwUll0ZEZQNGVVazVQUGo2NXFmVVJVZCtzUVFUNzZlczBocllyVFI3cDZpbGpzalZ6SGI5Q0NUbVJoYW1OejhQL2xnNFAxSUVrYUhlMElBNklLZUZXeFRwbWlFMytmWHl3K1hqbzF5WFZXUGgzaHZUTUhUbG1iUTF1SHpyaTUrb1lSaGpPQ2FLQTBYUzJNYkN4dXBzRVFTdUJYZmFQUDZEVVFIdnpxUjBDVXNBU1pEbU43NjVTczJDZTlneG9kbXJac1lXMEFsK0tQZ1V5bmd0bjA2Q1hyQlorWTQ5WVR2NFpFdlJ1WDNrdTJTazBTYjNRMXBHZDNjR2gxeW5scHpvM2hwWnRUZytDdDdtcFVKQURNdHdZa05QTG56TE5PdmNzbGIzNE5TbWdMREJEeTV0NGhOVFJCYWdGL0ZhK3JjdkNGK0lYWkdOZXNNclpMVmR5b29LTGRwNHptYk8yaEo1OUVlTE9RYUtZbkhtUWNLRU9oNjBBdktvZFZuMGVBbWxYc1YzRkRyZkp2ZE9QOURlOHk4OUV3VXpzc3U2MnE1aUJ2REs1SG90WDMybW9Jam1ncnRRcWQxaHRUeVlVMEJoTGFuRE5sSEtTdUp0UVlqQVl4MzN1UnZsZE8yQTA1cEpHdUd0UDRNQkhjTmFEUlV0WTNyamhOUnBnNDB2RndVNHZWSFVRVWZCVGdJNXNJY2pCOUlVUytpVWQ3VFg5ZUxhSnpaV3hGR2pRWm9JRVN3b0NrWlAwNnVKTmV1VGpMa3htWXBQcCtyVXpqdG5IU0Y4Q3ZhdWhtSkxsTVZyeEQxb3RDSXAzWkUxd0ZXVG9WV000Qjh5NlA2ZzB2ajJqSWw1RitYeG5RZzZaNVdqS1A3UjhGaWJMOVpNNEZMR1VoTzdlTWRzU1YxK1VNQytzZFJrVnM1ZjYyVys0T2Jld3FacTI3Qy8wdDJ4NEYrUG16QU92alpqcG1KbnI5RU5WZGZMVk1VZGNJeUJiMVhuVHJrRWw3UnNRQkxsa1FPOHM0cEt4eDdYazNTeCt6NGcxTm8xY1pXaHFWdFZ5bklkOXYxdU9jVklBYUE9'
});
console.log(JSON.parse(x).challenge);
//03AHJ_VuuiaIB_izO6VJ6PifXI8A8i1yBeG6biCjadtaZHk5pbxfbW5JPpEXBEay-LPdCzSOI1bQgdnjq1tQVSqzQ63hMQB1Sjlho4LdzfZKLXuK3TKZD1YPr5bIjM-dYqHIkcYpaanchXOXLkHNoj0B6_ZrUk4rZg-o790H1LMNzoPGy3qkk6suYWs1CERFjkTO_mw9puMnYQNITPzBnRS-QMilbch2d_PeM2aDGToLSQiLn8mgHwP7fUHvCcE9VGzNZNXkDC8wF-YvUCxU354VqeSa8U7KKycg
In the browser
This should work on client-side JavaScript :
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU";
document.body.appendChild(js);
It adds the external file to your HTML. The JavaScript inside is run once it's been loaded.
Node.js
In node, I'd take this road :
Do an HTTP request to get the code
Save that code as a text file
require the file you just saved
If you take that road, your code should look something like this :
require("request")("http://www.google.com/recaptcha/api/challenge?k=6Leluc8SAAAAAElzN1CrcweqVxkUfmGa7QC40pUU", function(error, response, body) {
require('fs').writeFile('./stuff.js', body, function(err) {
if(err) {
return console.log(err);
}
var stuffIJustLoaded = require('./stuff.js');
});
});
Here's what I'm trying to do:
From an html page using only Javascript I'm trying to query the Active Directory and retrieve some user's attributes.
Which I succeded to do (thanks to some helpful code found around that I just cleaned up a bit).
I can for example display on my html page the "displayName" of the user I provided the "samAccountName" in my code, which is great.
But I also wanted to display the "thumbnailPhoto" and here I'm getting some issues...
I know that the AD provide the "thumbnailPhoto" as a byte array and that I should be able to display it in a tag as follow:
<img src="data:image/jpeg;base64," />
including base64 encoded byte array at the end of the src attribute.
But I cannot manage to encode it at all.
I tried to use the following library for base64 encoding:
https://github.com/beatgammit/base64-js
But was unsuccesful, it's acting like nothing is returned for that AD attribute, but the photo is really there I can see it over Outlook or Lync.
Also when I directly put that returned value in the console I can see some weird charaters so I guess there's something but not sure how it should be handled.
Tried a typeof to find out what the variable type is but it's returning "undefined".
I'm adding here the code I use:
var ADConnection = new ActiveXObject( "ADODB.connection" );
var ADCommand = new ActiveXObject( "ADODB.Command" );
ADConnection.Open( "Data Source=Active Directory Provider;Provider=ADsDSOObject" );
ADCommand.ActiveConnection = ADConnection;
var ou = "DC=XX,DC=XXXX,DC=XXX";
var where = "objectCategory = 'user' AND objectClass='user' AND samaccountname='XXXXXXXX'";
var orderby = "samaccountname ASC";
var fields = "displayName,thumbnailPhoto";
var queryType = fields.match( /,(memberof|member),/ig ) ? "LDAP" : "GC";
var path = queryType + "://" + ou;
ADCommand.CommandText = "select '" + fields + "' from '" + path + "' WHERE " + where + " ORDER BY " + orderby;
var recordSet = ADCommand.Execute;
fields = fields.split( "," );
var data = [];
while(!recordSet.EOF)
{
var rowResult = { "length" : fields.length };
var i = fields.length;
while(i--)
{
var fieldName = fields[i];
if(fieldName == "directReports" && recordSet.Fields(fieldName).value != null)
{
rowResult[fieldName] = true;
}
else
{
rowResult[fieldName] = recordSet.Fields(fieldName).value;
}
}
data.push(rowResult);
recordSet.MoveNext;
}
recordSet.Close();
console.log(rowResult["displayName"]);
console.log(rowResult["thumbnailPhoto"]);
(I replaced db information by Xs)
(There's only one entry returned that's why I'm using the rowResult in the console instead of data)
And here's what the console returns:
LOG: Lastname, Firstname
LOG: က䙊䙉Āā怀怀
(same here Lastname & Firstname returned are the correct value expected)
This is all running on IE9 and unfortunetly have to make this compatible with IE9 :/
Summary:
I need to find a solution in Javascript only
I know it should be returning a byte array and I need to base64 encode it, but all my attempts failed and I'm a bit clueless on the reason why
I'm not sure if the picture is getting returned at all here, the thing in the console seems pretty small... or if I'm nothing doing the encoding correctly
If someone could help me out with this it would be awesome, I'm struggling with this for so long now :/
Thanks!
Im working with a lot of datas which i turned into arrays , for simplicity lets assume i have array that looks like this
["dataone:dataone","datatwo:datatwo","datathree:datathree"]
im writting output to the file using fs.writeFile
but the output is always in the same row e.g dataone:dataone","datatwo:datatwo","datathree:datathree
i would like to output to be like with "\n" e.g
dataone:dataone
datatwo:datatwo
datathree:datathree
is it possible to make output in file look like this? im writting in into .txt file
Join the data with line breaks before writing to file
var os = require('os');
var brk = os.platform().substring(0,3).toLowerCasee() === 'win'
? '\r\n' : '\n';
var data = ["dataone:dataone","datatwo:datatwo","datathree:datathree"]
fs.writeFile(filename, data.join(brk), {encoding : 'utf8'}, function (e) {
// etc
});
You can join your array with \n before writing it to the file:
var arr = ["dataone:dataone","datatwo:datatwo","datathree:datathree"]
var arr2 = arr.join('\n');
I'm currently using .resx files to manage my server side resources for .NET.
the application that I am dealing with also allows developers to plugin JavaScript into various event handlers for client side validation, etc.. What is the best way for me to localize my JavaScript messages and strings?
Ideally, I would like to store the strings in the .resx files to keep them with the rest of the localized resources.
I'm open to suggestions.
A basic JavaScript object is an associative array, so it can easily be used to store key/value pairs. So using JSON, you could create an object for each string to be localized like this:
var localizedStrings={
confirmMessage:{
'en/US':'Are you sure?',
'fr/FR':'Est-ce que vous êtes certain?',
...
},
...
}
Then you could get the locale version of each string like this:
var locale='en/US';
var confirm=localizedStrings['confirmMessage'][locale];
Inspired by SproutCore You can set properties of
strings:
'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';
and then simply spit out the proper localization based on your locale:
var locale = 'en';
alert( message[locale] );
After Googling a lot and not satisfied with the majority of solutions presented, I have just found an amazing/generic solution that uses T4 templates. The complete post by Jochen van Wylick you can read here:
Using T4 for localizing JavaScript resources based on .resx files
Main advantages are:
Having only 1 place where resources are managed ( namely the .resx
files )
Support for multiple cultures
Leverage IntelliSense - allow for code completion
Disadvantages:
The shortcomings of this solution are of course that the size of the
.js file might become quite large. However, since it's cached by the
browser, we don't consider this a problem for our application. However
- this caching can also result in the browser not finding the resource called from code.
How this works?
Basically he defined a T4 template that points to your .resx files. With some C# code he traverses each and every resource string and add it to JavaScript pure key value properties that then are output in a single JavaScript file called Resources.js (you can tweak the names if you wish).
T4 template [ change accordingly to point to your .resx files location ]
<## template language="C#" debug="false" hostspecific="true"#>
<## assembly name="System.Windows.Forms" #>
<## import namespace="System.Resources" #>
<## import namespace="System.Collections" #>
<## import namespace="System.IO" #>
<## output extension=".js"#>
<#
var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
var resourceNames = new string[1]
{
"Common"
};
#>
/**
* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
**/
var Resources = {
<# foreach (var name in resourceNames) { #>
<#=name #>: {},
<# } #>
};
<# foreach (var name in resourceNames) {
var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
var enFile = Host.ResolvePath(path + name + ".resx" );
ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
ResXResourceSet enResxSet = new ResXResourceSet(enFile);
#>
<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = {
'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
};
<# } #>
<# } #>
In the Form/View side
To have the correct translation picked up, add this in your master if you're using WebForms:
<script type="text/javascript">
var locale = '<%= System.Threading.Thread.CurrentThread.CurrentCulture.Name %>';
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
If you're using ASP.NET MVC (like me), you can do this:
<script type="text/javascript">
// Setting Locale that will be used by JavaScript translations
var locale = $("meta[name='accept-language']").attr("content");
</script>
<script type="text/javascript" src="/Scripts/Resources.js"></script>
The MetaAcceptLanguage helper I got from this awesome post by Scott Hanselman:
Globalization, Internationalization and Localization in ASP.NET MVC 3, JavaScript and jQuery - Part 1
public static IHtmlString MetaAcceptLanguage<T>(this HtmlHelper<T> html)
{
var acceptLanguage =
HttpUtility.HtmlAttributeEncode(
Thread.CurrentThread.CurrentUICulture.ToString());
return new HtmlString(
String.Format("<meta name=\"{0}\" content=\"{1}\">", "accept-language",
acceptLanguage));
}
Use it
var msg = Resources.Common.Greeting[locale];
alert(msg);
With a satellite assembly (instead of a resx file) you can enumerate all strings on the server, where you know the language, thus generating a Javascript object with only the strings for the correct language.
Something like this works for us (VB.NET code):
Dim rm As New ResourceManager([resource name], [your assembly])
Dim rs As ResourceSet =
rm.GetResourceSet(Thread.CurrentThread.CurrentCulture, True, True)
For Each kvp As DictionaryEntry In rs
[Write out kvp.Key and kvp.Value]
Next
However, we haven't found a way to do this for .resx files yet, sadly.
JSGettext does an excellent job -- dynamic loading of GNU Gettext .po files using pretty much any language on the backend. Google for "Dynamic Javascript localization with Gettext and PHP" to find a walkthrough for JSGettext with PHP (I'd post the link, but this silly site won't let me, sigh...)
Edit: this should be the link
I would use an object/array notation:
var phrases={};
phrases['fatalError'] ='On no!';
Then you can just swap the JS file, or use an Ajax call to redefine your phrase list.
There's a library for localizing JavaScript applications:
https://github.com/wikimedia/jquery.i18n
It can do parameter replacement, supports gender (clever he/she handling), number (clever plural handling, including languages that have more than one plural form), and custom grammar rules that some languages need.
The strings are stored in JSON files.
The only requirement is jQuery.
I did the following to localize JavaScript for a mobile app running HTML5:
1.Created a set of resource files for each language calling them like "en.js" for English. Each contained the different strings the app as follows:
var localString = {
appName: "your app name",
message1: "blah blah"
};
2.Used Lazyload to load the proper resource file based on the locale language of the app: https://github.com/rgrove/lazyload
3.Pass the language code via a Query String (As I am launching the html file from Android using PhoneGap)
4.Then I wrote the following code to load dynamically the proper resource file:
var lang = getQueryString("language");
localization(lang);
function localization(languageCode) {
try {
var defaultLang = "en";
var resourcesFolder = "values/";
if(!languageCode || languageCode.length == 0)
languageCode = defaultLang;
// var LOCALIZATION = null;
LazyLoad.js(resourcesFolder + languageCode + ".js", function() {
if( typeof LOCALIZATION == 'undefined') {
LazyLoad.js(resourcesFolder + defaultLang + ".js", function() {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
});
} else {
for(var propertyName in LOCALIZATION) {
$("#" + propertyName).html(LOCALIZATION[propertyName]);
}
}
});
} catch (e) {
errorEvent(e);
}
}
function getQueryString(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
5.From the html file I refer to the strings as follows:
span id="appName"
Well, I think that you can consider this. English-Spanish example:
Write 2 Js Scripts, like that:
en-GB.js
lang = {
date_message: 'The start date is incorrect',
...
};
es-ES.js
lang = {
date_message: 'Fecha de inicio incorrecta',
...
};
Server side - code behind:
Protected Overrides Sub InitializeCulture()
Dim sLang As String
sLang = "es-ES"
Me.Culture = sLang
Me.UICulture = sLang
Page.ClientScript.RegisterClientScriptInclude(sLang & ".js", "../Scripts/" & sLang & ".js")
MyBase.InitializeCulture()
End Sub
Where sLang could be "en-GB", you know, depending on current user's selection ...
Javascript calls:
alert (lang.date_message);
And it works, very easy, I think.
Expanding on diodeus.myopenid.com's answer: Have your code write out a file containing a JS array with all the required strings, then load the appropriate file/script before the other JS code.
The MSDN way of doing it, basically is:
You create a separate script file for each supported language and culture. In each script file, you include an object in JSON format that contains the localized resources values for that language and culture.
I can't tell you the best solution for your question, but IMHO this is the worst way of doing it. At least now you know how NOT to do it.
We use MVC and have simply created a controller action to return a localized string. We maintain the user's culture in session and set the thread culture before any call to retrieve a language string, AJAX or otherwise. This means we always return a localized string.
I'll admit, it isn't the most efficient method but getting a localised string in javascript is seldom required as most localization is done in our partial views.
Global.asax.cs
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
// Set the current thread's culture
var culture = (CultureInfo)Session["CultureInfo"];
if (culture != null)
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
Controller Action
public string GetString(string key)
{
return Language.ResourceManager.GetString(key);
}
Javascript
/*
Retrieve a localized language string given a lookup key.
Example use:
var str = language.getString('MyString');
*/
var language = new function () {
this.getString = function (key) {
var retVal = '';
$.ajax({
url: rootUrl + 'Language/GetString?key=' + key,
async: false,
success: function (results) {
retVal = results;
}
});
return retVal;
}
};