1// Tracks whether the visitor has made unsaved changes to a simpleform, so we can warn 2// before navigating away (back button, closing the tab, following a link, refreshing). 3// Reset to false on every intentional submit within applySimpleforms below, so paging 4// through the wizard (Volgende/Vorige/Verzenden/Ga naar pagina) never triggers the warning. 5var simpleFormDirty = false; 6 7window.addEventListener('beforeunload', function(event) { 8 if (simpleFormDirty) { 9 // Standard-compliant browsers require preventing the default action. 10 event.preventDefault(); 11 // Included for legacy support in older browsers. The actual text is ignored by 12 // modern browsers, which show their own fixed "changes may not be saved" message. 13 event.returnValue = ''; 14 } 15}); 16 17var SimpleForm = Class.create({ 18 form: null, 19 questionSelector: '.question', 20 inputFieldSelector: '.inputfield', 21 hintElementSelector: 'span.hint', 22 initialize: function(form) { 23 this.form = $(form); 24 this.prepareForm(); 25 this.form.select(this.questionSelector).each(this.prepareQuestion.bind(this)); 26 // focus the right element: 27 try { 28 var errorContainer; 29 if( (errorContainer = this.form.down(this.questionSelector + '.error')) ) { 30 errorContainer.down(this.inputFieldSelector).activate(); 31 } 32 } catch(e) { } 33 }, 34 prepareForm: function prepareForm() { 35 var warningp = new Element('h2', { class: "warning", role:"alert" }).update("U heeft een vraag / aantal vragen niet of niet correct ingevuld."); 36 var warningul = new Element('ul', { class: "warningslist" }); 37 var warnings = this.form.select("ul.warnings"); 38 if(warnings.length > 0) { 39 this.form.insert({before: warningp}); 40 this.form.insert({before: warningul}); 41 42 warnings.each(function (element) { 43 44 var questionWrapper = element.up(".question"); 45 var questionText = questionWrapper.querySelector('.labeltitle').innerHTML; 46 if(questionText) { 47 var hintElem = questionWrapper.down("span.hint"); 48 if(hintElem){ 49 hintElem.removeClassName("hidden").addClassName("donthide") 50 } 51 } 52 element.select("li").each(function (elementLi) { 53 var topWarningElement = elementLi.clone(true); 54 topWarningElement.update(questionText + ": " + topWarningElement.innerHTML); 55 warningul.insert(topWarningElement); 56 }); 57 }); 58 } 59 }, 60 prepareQuestion: function prepareQuestion(container) { 61 var hint, firstElement, inputField = container.down(this.inputFieldSelector), readOnly = false, 62 hideHint = function() { hint.addClassName('hidden'); } 63 if(inputField) { 64 readOnly = inputField.readAttribute('readonly') === 'readonly'; 65 } 66 if(!container.next(this.questionSelector)) { 67 container.addClassName('last-child'); 68 } 69 if( (hint = container.down(this.hintElementSelector)) ) { 70 firstElement = container.down(this.inputFieldSelector); 71 // IE triggers click when focus() is called: 72 hint.ignoreClick = false; 73 if(!hint.hasClassName("donthide")) { 74 hint.addClassName('hidden').observe('click', hideHint); 75 } 76 77 container.select(this.inputFieldSelector) 78 .invoke('observe', 'click', function() { if(!hint.ignoreClick) { hideHint(); } hint.ignoreClick = false; }) 79 .invoke('observe', 'blur', hideHint) 80 .invoke('observe', 'focus', hideHint); 81 82 // Place the hint text after the correct html tag. 83 var tag; 84 if (container.hasClassName("checkfields")) { 85 tag = "legend"; 86 } else if (container.hasClassName("timefield")) { 87 tag = "legend"; 88 } else { 89 tag = "label"; 90 } 91 92 var labelText = container.querySelector('.labeltitle').innerHTML; 93 container.down(tag).after( 94 new Element('button', {href: '#' + firstElement.identify(), 'aria-expanded':"false"}).addClassName('hint-toggle').update('<span>Toon de helptekst voor de vraag: '+labelText+'</span>').observe('click', function showHint(event) { 95 var anchor = event.findElement('button'), offsetLeft = 0, checkedElement; 96 event.stop(); 97 if(!event.defaultPrevented) { 98 anchor.href = '#'; 99 } 100 var ariatoggle = anchor.getAttribute("aria-expanded"); 101 if (ariatoggle === "true") { 102 ariatoggle = "false"; 103 anchor.removeAttribute("aria-describedby"); 104 hint.addClassName('hidden'); 105 } else { 106 ariatoggle = "true"; 107 anchor.setAttribute("aria-describedby", 'hint-' + firstElement.identify()) ; 108 hint.removeClassName('hidden'); 109 } 110 anchor.setAttribute("aria-expanded", ariatoggle); 111 }.bind(this)).observe('blur', function hideHint(event) { 112 var anchor = event.findElement('button'), offsetLeft = 0, checkedElement; 113 event.stop(); 114 anchor.setAttribute("aria-expanded", "false"); 115 anchor.removeAttribute("aria-describedby"); 116 hint.addClassName('hidden'); 117 }.bind(this)) 118 ); 119 } 120 if(container.hasClassName('change-submit')) { 121 container.select(this.inputFieldSelector).invoke('observe', 'change', function submitForm(event) { 122 this.form.submit(); 123 }.bind(this)); 124 } 125 if(container.hasClassName('password') && container.hasClassName('strength-indicator') && !readOnly) { 126 this.addStrengthIndicator(inputField); 127 } 128 if(container.hasClassName('datefield') && !readOnly) { 129 // rs_reserve prevents ReadSpeaker altering the code. 130 container.down('input').addClassName('rs_preserve'); 131 this.addCalendar(container); 132 } 133 if(container.hasClassName('datefield_week') && !readOnly) { 134 this.addCalendar_week(container); 135 } 136 if(container.hasClassName('timefield') && !readOnly) { 137 this.addTime(container); 138 } 139 if(container.hasClassName('geofield')) { 140 this.addMap(container); 141 } 142 if(container.hasClassName('webeditor')) { 143 this.addWebeditor.bind(this).defer(container); 144 } 145 // convert select to calendar: 146 if(container.hasClassName('calendarselect')) { 147 new Calendar({ 148 targetInput: container.down(this.inputFieldSelector), 149 container: container, 150 hideTargetInput: true, 151 sourceFormat: 'dd-MM-yyyy', 152 showWeeks: false, 153 className: 'inline-calendar' 154 }); 155 } 156 }, 157 /** 158 * Based on the implementation of Jeff Todnem (http://www.todnem.com/) 159 */ 160 calculatePasswordStrength: function calculatePasswordStrength(pwd) { 161 var nLength = pwd.length, nAlphaUC = 0, nAlphaLC = 0, nNumber = 0, nSymbol = 0, nMidChar = 0, 162 nAlphasOnly = 0, nNumbersOnly = 0, nUnqChar = 0, nRepChar = 0, nRepInc = 0, nConsecAlphaUC = 0, 163 nConsecAlphaLC = 0, nConsecNumber = 0, nConsecSymbol = 0, nConsecCharType = 0, nSeqAlp
163ha = 0, 164 nSeqNumber = 0, nSeqSymbol = 0, nSeqChar = 0, nMultMidChar = 2, nMultConsecAlphaUC = 2, 165 nMultConsecAlphaLC = 2, nMultConsecNumber = 2, nMultSeqAlpha = 3, nMultSeqNumber = 3, 166 nMultSeqSymbol = 3, nMultLength = 4, nMultNumber = 4, nMultSymbol = 6, nTmpAlphaUC = "", 167 nTmpAlphaLC = "", nTmpNumber = "", nTmpSymbol = "", nScore = parseInt(nLength * nMultLength), 168 sAlphas = "abcdefghijklmnopqrstuvwxyz", sNumerics = "01234567890", sSymbols = ")!@#$%^&*()", 169 arrPwd = pwd.replace(/\s+/g,"").split(/\s*/), arrPwdLen = arrPwd.length, a, s, sFwd, sRev, 170 strReverse = function(string) { 171 var newstring = "", s; 172 for (s = 0; s < string.length; s++) { 173 newstring = string.charAt(s) + newstring; 174 } 175 return newstring; 176 }; 177 178 /* Loop through password to check for Symbol, Numeric, Lowercase and Uppercase pattern matches */ 179 for (a = 0; a < arrPwdLen; a++) { 180 if (arrPwd[a].match(/[A-Z]/g)) { 181 if (nTmpAlphaUC !== "") { if ((nTmpAlphaUC + 1) == a) { nConsecAlphaUC++; nConsecCharType++; } } 182 nTmpAlphaUC = a; 183 nAlphaUC++; 184 } 185 else if (arrPwd[a].match(/[a-z]/g)) { 186 if (nTmpAlphaLC !== "") { if ((nTmpAlphaLC + 1) == a) { nConsecAlphaLC++; nConsecCharType++; } } 187 nTmpAlphaLC = a; 188 nAlphaLC++; 189 } 190 else if (arrPwd[a].match(/[0-9]/g)) { 191 if (a > 0 && a < (arrPwdLen - 1)) { nMidChar++; } 192 if (nTmpNumber !== "") { if ((nTmpNumber + 1) == a) { nConsecNumber++; nConsecCharType++; } } 193 nTmpNumber = a; 194 nNumber++; 195 } 196 else if (arrPwd[a].match(/[^a-zA-Z0-9_]/g)) { 197 if (a > 0 && a < (arrPwdLen - 1)) { nMidChar++; } 198 if (nTmpSymbol !== "") { if ((nTmpSymbol + 1) == a) { nConsecSymbol++; nConsecCharType++; } } 199 nTmpSymbol = a; 200 nSymbol++; 201 } 202 /* Internal loop through password to check for repeat characters */ 203 var bCharExists = false; 204 for (var b=0; b < arrPwdLen; b++) { 205 if (arrPwd[a] == arrPwd[b] && a != b) { /* repeat character exists */ 206 bCharExists = true; 207 nRepInc += Math.abs(arrPwdLen/(b-a)); 208 } 209 } 210 if (bCharExists) { 211 nRepChar++; 212 nUnqChar = arrPwdLen-nRepChar; 213 nRepInc = (nUnqChar) ? Math.ceil(nRepInc/nUnqChar) : Math.ceil(nRepInc); 214 } 215 } 216 217 /* Check for sequential alpha string patterns (forward and reverse) */ 218 for (s = 0; s < 23; s++) { 219 sFwd = sAlphas.substring(s,parseInt(s+3)); 220 sRev = strReverse(sFwd); 221 if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqAlpha++; nSeqChar++;} 222 } 223 224 /* Check for sequential numeric string patterns (forward and reverse) */ 225 for (s = 0; s < 8; s++) { 226 sFwd = sNumerics.substring(s,parseInt(s+3)); 227 sRev = strReverse(sFwd); 228 if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqNumber++; nSeqChar++;} 229 } 230 231 /* Check for sequential symbol string patterns (forward and reverse) */ 232 for (s = 0; s < 8; s++) { 233 sFwd = sSymbols.substring(s,parseInt(s+3)); 234 sRev = strReverse(sFwd); 235 if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqSymbol++; nSeqChar++;} 236 } 237 238 /* Modify overall score value based on usage vs requirements */ 239 240 /* General point assignment */ 241 if (nAlphaUC > 0 && nAlphaUC < nLength) { 242 nScore = parseInt(nScore + ((nLength - nAlphaUC) * 2)); 243 } 244 if (nAlphaLC > 0 && nAlphaLC < nLength) { 245 nScore = parseInt(nScore + ((nLength - nAlphaLC) * 2)); 246 } 247 if (nNumber > 0 && nNumber < nLength) { 248 nScore = parseInt(nScore + (nNumber * nMultNumber)); 249 } 250 if (nSymbol > 0) { 251 nScore = parseInt(nScore + (nSymbol * nMultSymbol)); 252 } 253 if (nMidChar > 0) { 254 nScore = parseInt(nScore + (nMidChar * nMultMidChar)); 255 } 256 257 /* Point deductions for poor practices */ 258 if ((nAlphaLC > 0 || nAlphaUC > 0) && nSymbol === 0 && nNumber === 0) { // Only Letters 259 nScore = parseInt(nScore - nLength); 260 nAlphasOnly = nLength; 261 } 262 if (nAlphaLC === 0 && nAlphaUC === 0 && nSymbol === 0 && nNumber > 0) { // Only Numbers 263 nScore = parseInt(nScore - nLength); 264 nNumbersOnly = nLength; 265 } 266 if (nRepChar > 0) { // Same character exists more than once 267 nScore = parseInt(nScore - nRepInc); 268 } 269 if (nConsecAlphaUC > 0) { // Consecutive Uppercase Letters exist 270 nScore = parseInt(nScore - (nConsecAlphaUC * nMultConsecAlphaUC)); 271 } 272 if (nConsecAlphaLC > 0) { // Consecutive Lowercase Letters exist 273 nScore = parseInt(nScore - (nConsecAlphaLC * nMultConsecAlphaLC)); 274 } 275 if (nConsecNumber > 0) { // Consecutive Numbers exist 276 nScore = parseInt(nScore - (nConsecNumber * nMultConsecNumber)); 277 } 278 if (nSeqAlpha > 0) { // Sequential alpha strings exist (3 characters or more)
279 nScore = parseInt(nScore - (nSeqAlpha * nMultSeqAlpha)); 280 } 281 if (nSeqNumber > 0) { // Sequential numeric strings exist (3 characters or more) 282 nScore = parseInt(nScore - (nSeqNumber * nMultSeqNumber)); 283 } 284 if (nSeqSymbol > 0) { // Sequential symbol strings exist (3 characters or more) 285 nScore = parseInt(nScore - (nSeqSymbol * nMultSeqSymbol)); 286 } 287 if (nScore > 100) { nScore = 100; } else if (nScore < 0) { nScore = 0; } 288 return nScore; 289 }, 290 addStrengthIndicator: function addStrengthIndicator(inputField) { 291 var indicator = new Element('span').addClassName('strength invisible').writeAttribute("aria-live", "polite").writeAttribute("role", "live").update('-'), 292 strengths = { 293 veryweak: 'Zeer zwak', 294 weak: 'Zwak', 295 good: 'Goed', 296 strong: 'Sterk', 297 verystrong: 'Zeer sterk' 298 }; 299 inputField.insert({ after: indicator }) 300 .observe('keyup', function updateStrength() { 301 var value = $F(inputField), score, strength; 302 if(value.empty()) { 303 indicator.className = 'strength invisible'; 304 } else { 305 score = this.calculatePasswordStrength(value); 306 if (score >= 0 && score < 20) { strength = 'veryweak'; } 307 else if (score >= 20 && score < 40) { strength = 'weak'; } 308 else if (score >= 40 && score < 60) { strength = 'good'; } 309 else if (score >= 60 && score < 80) { strength = 'strong'; } 310 else if (score >= 80 && score <= 100) { strength = 'verystrong'; } 311 if(score === 0) { score = 1; } 312 indicator.setStyle({ width: score + '%' }).update(strengths[strength]).className = 'strength ' + strength; 313 } 314 }.bind(this)); 315 }, 316 addCalendar: function addCalendar(container) { 317 var anchor = container.down('.calendar_button'), 318 target = container.down(this.inputFieldSelector); 319 if (!anchor) { 320 // rs_reserve prevents ReadSpeaker altering the code. 321 anchor = new Element('button', { 'class': 'calendar-button rs_preserve', href: 'calendar:show' }).update('Kalender') 322 target.insert({ 323 after: anchor 324 }); 325 } 326 new Calendar({ 327 container: container, 328 anchor: anchor, 329 targetInput: target, 330 returnFormat: 'dd-MM-yyyy', 331 hideTargetInput: false, 332 showWeeks: false, 333 className: 'popup-calendar' 334 }); 335 }, 336 addCalendar_week: function addCalendar_week(container) { 337 var anchor = container.down('.calendar_button'), 338 target = container.down(this.inputFieldSelector); 339 if (!anchor) { 340 // rs_reserve prevents ReadSpeaker altering the code. 341 anchor = new Element('button', { 'class': 'calendar-button rs_preserve', href: 'calendar:show' }).update('Kalender') 342 target.insert({ 343 after: anchor 344 }); 345 } 346 new WeekSelectCalendar({ 347 container: container, 348 anchor: anchor, 349 targetInput: target, 350 sourceFormat: 'dd-MM-yyyy', 351 returnFormat: 'dd-MM-yyyy', 352 hideTargetInput: false, 353 showWeeks: true, 354 className: 'popup-calendar' 355 }); 356 }, 357 addTime: function addTime(container) { 358 // rs_reserve prevents ReadSpeaker altering the code. 359 container.down('div').insert(new Element('button').addClassName('set rs_preserve').writeAttribute("tabindex", "0").update('Nu').observe('click', function setNow(event) { 360 event.stop(); 361 var selects = event.findElement(this.questionSelector).select('select') 362 date = new Date(); 363 if (selects.size() === 2) { 364 [date.getHours(), date.getMinutes()].each(function (value, index) { 365 selects[index].setValue(value); 366 }); 367 } 368 }.bind(this))); 369 }, 370/* addWebeditor: function addWebeditor(container) { 371 var textarea = container.down('textarea'); 372 if (typeof CKEDITOR != 'undefined') { 373 if (!CKEDITOR.instances[textarea.name]) { 374 CKEDITOR.replace(textarea, { 375 customConfig: '', // don't load the external config.js file 376 contentsCss: [stylesPath + '/content.css.jsp', contextpath + '/js/ckeditor/gv-contents.css'], 377 baseFloatZIndex: 200005, // the dsedit modal mask is z-indexed at 200000 378 toolbar: 'simpleform', 379 height: 200, 380 skin: 'moono-lisa', 381 // language 382 language: 'nl', 383 // toolbar presets 384 toolbar_simpleform: [ 385 { name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'] },
386 { name: 'editing', items: ['Find', 'Replace'] }, 387 { name: 'insert', items: ['Image', 'Table', 'SpecialChar'] }, 388 { name: 'styles', items: ['Styles', 'Format', 'gvLanguageSelect'] }, 389 '/', 390 { name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', 'Abbr', '-', 'RemoveFormat'] }, 391 { name: 'links', items: ['Link', 'Unlink', 'Anchor'] }, 392 { name: 'paragraph', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl'] } 393 ], 394 // style select presets: 395 stylesSet: [ 396 { name: 'Call-to-action',element:'a', attributes: { 'class': 'calltoaction' }}, 397 { name: 'CTA nieuw venster + ander domein',element:'a', attributes: { 'class': 'calltoaction new-window external' }}, 398 { name: 'CTA nieuw venster',element:'a', attributes: { 'class': 'calltoaction new-window' }}, 399 { name: 'CTA ander domein',element:'a', attributes: { 'class': 'calltoaction external' }}, 400 { name: 'Strong Emphasis', element: 'strong' }, 401 { name: 'Emphasis', element: 'em' }, 402 //{ name: 'Computer Code', element: 'code' }, 403 //{ name: 'Keyboard Phrase', element: 'kbd' }, 404 //{ name: 'Sample Text', element: 'samp' }, 405 //{ name: 'Variable', element: 'var' }, 406 //{ name: 'Deleted Text', element: 'del' }, 407 //{ name: 'Inserted Text', element: 'ins' }, 408 { name: 'Cited Work', element: 'cite' }, 409 { name: 'Inline Quotation', element: 'q' } 410 ], 411 // adjustments for valid (and semantic) output: 412 coreStyles_bold: { element: 'span', attributes: { 'class': 'bold' }}, 413 coreStyles_italic: { element: 'span', attributes: { 'class': 'italic' }}, 414 coreStyles_underline: { element: 'span', attributes: { 'class': 'underline' }}, 415 coreStyles_strike: { element: 'span', attributes: { 'class': 'strike' }}, 416 // add abbr and acronym to the tags to be removed by removeFormat: 417 removeFormatTags: CKEDITOR.config.removeFormatTags + ',abbr,acronym', 418 disableObjectResizing: true, 419 // editor resizing: 420 resize_dir: 'vertical', 421 toolbarCanCollapse: false 422 }); 423 } 424 } else { 425 throw "CK Editor is not loaded."; 426 } 427 }, */ 428 addMap: function addMap(container) { 429 var mapElement = container.down('div.google-map'), 430 questionId = null, 431 markerData = $A(), 432 map = new SimpleformMap(mapElement, { 433 displayElement: container.down('p.display'), 434 addressInput: container.down('input.address'), 435 centerInput: container.down('input.center'), 436 valueInput: container.down('input.values'), 437 zoomInput: container.down('input.zoom'), 438 onCreate: function onCreate() { 439 var isEditable = true, originalCenter = this.getCenter(), originalZoom = this.getZoom(), zoomRevert = null, centerRevert = null; 440 if(this.valueInput.readAttribute('readonly')) { 441 isEditable = false; 442 } 443 if(isEditable) { 444 // click observer: 445 google.maps.event.addListener(this.map, 'click', function mapClickHandler(gEvent) { 446 if(this.addSimpleFormMarker(gEvent.latLng)) { 447 this.geocodelatLng(gEvent.latLng, this.displayAddress.bind(this)); 448 } 449 }.bind(this)); 450 // zoom observer: 451 google.maps.event.addListener(this.map, 'zoom_changed', function saveCenter() { 452 this.zoomInput.setValue(this.getZoom()); 453 }.bind(this)); 454 // center observer: 455 google.maps.event.addListener(this.map, 'center_changed', function saveCenter() { 456 this.centerInput.setValue(this.getCenter().toString()); 457 }.bind(this)); 458 } else { 459 google.maps.event.addListener(this.map, 'zoom_changed', function saveCenter() { 460 if(zoomRevert) { clearTimeout(zoomRevert); } 461 zoomRevert = this.setZoom.bind(this).delay(2, originalZoom); 462 }.bind(this)); 463 google.maps.event.addListener(this.map, 'dragend', function saveCenter() { 464 if(centerRevert) { clearTimeout(centerRevert); } 465 centerRevert = this.map.panTo.bind(this.map).delay(2, originalCenter); 466 }.bind(this)); 467 } 468 469 if( (questionId = mapElement.readAttribute('id')) && window.simpleFormMaps[questionId]) { 470 markerData = window.simpleFormMaps[questionId]; 471 } 472 // load data: 473 markerData.each(function loadMarker(m) { 474 var draggable = m.selected; 475 if(!isEditable) { 476 draggable = false;
477 } 478 this.addSimpleFormMarker(this.strToLatLng(m.coords), m.text, draggable); 479 }.bind(this)); 480 } 481 }); 482 } 483}); 484 485/** 486 * Google Map class specificly for Simpleforms 487 */ 488var SimpleformMap = Class.create(GoogleMap, { 489 maxMarkers: -1, 490 initialize: function initialize($super, container, params) { 491 $super(container, params); 492 this.maxMarkers = (e = this.container.down('span.max-markers')) ? parseInt(e.hide().innerHTML) : this.maxMarkers; 493 }, 494 // display geocoding results: 495 displayAddress: function displayAddress(results) { 496 if(results[0]) { 497 var display = results[0].formatted_address; 498 this.displayElement.update(this.displayElement.readAttribute('title') + ': ' + display); 499 this.addressInput.setValue(display); 500 } 501 }, 502 // saves the marker data: 503 saveMarkers: function saveMarkers() { 504 var data = $A(); 505 this.markers.each(function getSaveData(m) { 506 data.push(m.position.toString() + ';' + m.getTitle() + ';' + m.getDraggable()); 507 }); 508 this.valueInput.setValue( data.join('|') ); 509 }, 510 addSimpleFormMarker: function addSimpleFormMarker(latLng, title, draggable) { 511 if(this.maxMarkers === -1 || this.markers.size() < this.maxMarkers) { 512 if(typeof draggable === "undefined") { 513 draggable = true; 514 } 515 var marker = this.addMarker(latLng, { 516 title: title || '', 517 draggable: draggable 518 }); 519 520 if(draggable) { 521 // click marker observer (show address) 522 google.maps.event.addListener(marker, 'click', function clickHandler(gEvent) { 523 this.geocodelatLng(gEvent.latLng, this.displayAddress.bind(this)); 524 }.bind(this)); 525 526 // double click marker observer (remove marker and save) 527 google.maps.event.addListener(marker, 'dblclick', function clickHandler(gEvent) { 528 for(var i = 0; i < this.markers.size(); i++) { 529 if(this.markers[i].position.equals(gEvent.latLng)) { 530 this.markers[i].setMap(null); 531 this.markers[i] = null; 532 } 533 } 534 this.markers = this.markers.compact(); 535 this.saveMarkers(); 536 }.bind(this)); 537 538 // drag marker observer (show address and save) 539 google.maps.event.addListener(marker, 'dragend', function dragEndHandler(gEvent) { 540 this.geocodelatLng(gEvent.latLng, this.displayAddress.bind(this)); 541 this.saveMarkers(); 542 }.bind(this)); 543 } 544 545 this.saveMarkers(); 546 return true; 547 } else { 548 if(this.errorWindow) { 549 this.errorWindow.close(); 550 } 551 this.errorWindow = new google.maps.InfoWindow({ 552 content: "<p style='display: block; height: 50px;'>- Verwijder punten door er op te dubbel klikken.<br />- Klik en versleep om het punt te verplaatsen.<br />- U kunt maximaal <strong>" + this.maxMarkers + "</strong> punt(en) toevoegen.<br /></p>", 553 position: latLng 554 }); 555 this.errorWindow.open(this.map); 556 return false; 557 } 558 } 559}); 560document.observe('dom:loaded', function applySimpleforms() { 561 $$('form.simpleform').each(function(form) { 562 if (!form.hasClassName('extended')) { 563 new SimpleForm(form); 564 // Any intentional submit (Volgende/Vorige/Verzenden/Ga naar pagina) is a legitimate 565 // navigation, not data loss - clear the flag so it doesn't trigger the warning. 566 form.observe('submit', function() { 567 simpleFormDirty = false; 568 }); 569 // The "ga naar pagina"/"terug naar" history form (simpleform's .formhistory class, 570 // decisiontree's identical select[name=goto] form) is page navigation, not form data 571 // - exclude it from dirty-tracking regardless of which template rendered it. 572 if (!form.hasClassName('formhistory') && !form.down('select[name="goto"]')) { 573 form.observe('input', function() { 574 simpleFormDirty = true; 575 }).observe('change', function() { 576 simpleFormDirty = true; 577 }); 578 } 579 } 580 }); 581 var link; 582 if( (link = $$("body")[0].down('.simpleform.end .target-link a[rel~=autovisit]')) ) { 583 (function(url) { 584 if(url) { 585 window.location.href = url; 586 } 587 }.curry(link.readAttribute('href'))).delay(1); 588 } 589});
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.