1 2(function ($) { 3 var handleFiles, ProgressBar, FileList, FileListInline; 4 5 $.fileTypeIcon = function (fileId, file) { 6 if (typeof file.type == 'undefined') { 7 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/default.png">'); 8 } else if(file.type.substring(0,6) == 'image/') { 9 return $('<img src="tiki-download_file.php?fileId=' + fileId + '&display&y=24" height="24">'); 10 } else if(file.type == 'application/pdf') { 11 return $('<img height="16" width="16" title="application/pdf" alt="application/pdf" src="img/icons/mime/pdf.png">'); 12 } else if(file.type.indexOf("sheet") != -1) { 13 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/xls.png">'); 14 } else if(file.type.indexOf("zip") != -1) { 15 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/zip.png">'); 16 } else if (file.type.substring(0,6) == 'video/') { 17 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/flv.png">'); 18 } else if (file.type.indexOf("word") != -1) { 19 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/doc.png">'); 20 } else { 21 return $('<img height="16" width="16" title="'+ file.type +'" alt="'+ file.type +'" src="img/icons/mime/default.png">'); 22 } 23 }; 24 25 ProgressBar = function (options) { 26 var bar = this; 27 this.segments = []; 28 this.updateSegment = function (number, current, total) { 29 bar.segments[number] = [current, total]; 30 bar.update(); 31 }; 32 this.update = function () { 33 var total = 0, current = 0; 34 $.each(bar.segments, function (k, item) { 35 current += item[0]; 36 total += item[1]; 37 }); 38 39 options.progress(current, total); 40 41 if (current === total) { 42 options.done(); 43 } 44 }; 45 }; 46 47 FileList = function (options) { 48 var $list = $(options.list); 49 this.clearErrors = function () { 50 $list.find('.text-danger').remove(); 51 }; 52 this.addError = function (file, message) { 53 var $li = $('<li>').appendTo($list); 54 55 $li.text(file.name); 56 $li.addClass('text-danger'); 57 $li.append(' (' + (message ? message : tr('uploading failed')) + ')'); 58 }; 59 this.addFile = function (fileId, file, title) { 60 // called for "upload in modal" tracker Files fields when file dropped or picked from the file dialog 61 var $li = $('<li>').addClass("row mb-4").appendTo($list); 62 63 var label = file.name; 64 if (title) { 65 label = title; 66 } 67 $("<div>").addClass("col-sm-12").text(label) 68 .prepend($.fileTypeIcon(fileId, file).css("margin-right", "1em")) 69 .appendTo($li); 70 71 72 if ($list.parents(".inline").length) { 73 var $fileInput = $list.parents(".files-field").find("> input"); 74 var val = $fileInput.val(); 75 val = val ? val + "," + fileId : fileId; 76 $fileInput.val(val); 77 } else { 78 $('<input type="hidden" name="file[]">') 79 .attr('value', fileId) 80 .appendTo($li); 81 82 if ($list.data("adddescription")) { 83 $("<label>") 84 .addClass("col-form-label col-sm-4") 85 .text(tr("Description")) 86 .appendTo($li); 87 $("<div>").addClass("col-sm-12") 88 .append($('<textarea name="description[]">') 89 .addClass("form-control col-sm-8") 90 ) 91 .appendTo($li); 92 } 93 } 94 95 }; 96 }; 97 98 handleFiles = function (input) { 99 100 var files = input.files, 101 accept = input.accept, 102 title = input.title, 103 galleryId = input.galleryId, 104 image_max_size_x = input.image_max_size_x, 105 image_max_size_y = input.image_max_size_y, 106 progressBar = input.progress, 107 ticket = input.ticket, 108 fileList = input.list, 109 $container = input.form, // sometimes a div when inline
110 $modal = $container.parents(".modal-dialog:first"); 111 112 if (! $modal.length) { 113 $modal = $container; 114 } 115 116 var uploadUrl = $.service('file', 'upload'); 117 118 var restoreExif = function(sourceImageData, newImageData){ 119 if (sourceImageData.indexOf('data:image/jpeg;base64,') !== 0){ 120 return newImageData; 121 } 122 var sourceImageSegments = MinifyJpeg.slice2Segments(MinifyJpeg.decode64(sourceImageData.replace("data:image/jpeg;base64,", ""))); 123 var exifInfo = MinifyJpeg.getExif(sourceImageSegments); 124 var newImageBinArray = MinifyJpeg.insertExif(newImageData, exifInfo); 125 return "data:image/jpeg;base64," + MinifyJpeg.encode64(newImageBinArray); 126 }; 127 128 $.each(files, function (k, file) { 129 var reader = new FileReader(); 130 131 progressBar.updateSegment(k, 0, file.size); 132 window.lastFile = file; 133 134 $(window).queue('process-upload', function () { 135 reader.onloadend = function (e) { 136 var xhr, provider, sendData, data, valid = true; 137 138 $modal.tikiModal(tr("Uploading file...")); 139 140 xhr = jQuery.ajaxSettings.xhr(); 141 if (xhr.upload) { 142 xhr.upload.addEventListener('progress', function (e) { 143 if (e.lengthComputable) { 144 progressBar.updateSegment(k, e.loaded, e.total); 145 } 146 }, false); 147 } 148 provider = function () { 149 return xhr; 150 }; 151 152 sendData = { 153 154 type: 'POST', 155 url: uploadUrl, 156 xhr: provider, 157 dataType: 'json', 158 global: false, // prevent ajaxError in tiki-jquery.js from closing the dialogs, leading to lost edits 159 success: function (data) { 160 fileList.addFile(data.fileId, file, title); 161 }, 162 error: function (jqXHR, textStatus, errorThrown) { 163 progressBar.updateSegment(k, 0, 0); 164 fileList.addError(file, errorThrown); 165 }, 166 complete: function (data, textStatus) { 167 $(window).dequeue('process-upload'); 168 169 if (data.responseJSON) { 170 ticket = data.responseJSON.ticket; 171 // for modal 172 if ($modal !== $container) { 173 $('form.file-uploader-result input[name=ticket]').val(ticket); 174 } 175 // for both (form when in modal, div when inline) 176 $container.data('ticket', ticket); 177 } else { 178 alert(tr("There was an error: " + textStatus)); 179 } 180 181 $modal.tikiModal(); 182 } 183 }; 184 185 if (window.FormData) { 186 sendData.processData = false; 187 sendData.contentType = false;
188 sendData.cache = false; 189 190 sendData.data = new FormData; 191 sendData.data.append('galleryId', galleryId); 192 sendData.data.append('image_max_size_x', image_max_size_x); 193 sendData.data.append('image_max_size_y', image_max_size_y); 194 sendData.data.append('ticket', ticket); 195 sendData.data.append('name', file.name); 196 sendData.data.append('title', title); 197 198 var waiting = false; 199 200 //checking if image is uploaded to call resize function and resizing options are set by tracker 201 // field creator 202 if (file.type.substring(0, 6) == 'image/' && (image_max_size_x || image_max_size_y)) { 203 waiting = true; 204 var imageData; 205 206 var picFile = e.target; 207 imageData = picFile.result; 208 209 var img = new Image(); 210 var blobImage = null; 211 img.src = imageData; 212 img.onload = function () { 213 var width = parseInt(image_max_size_x); 214 var height = parseInt(image_max_size_y); 215 var image_x = parseInt(image_max_size_x); 216 var image_y = parseInt(image_max_size_y); 217 var ratio; 218 if (img.width > image_x || img.height > image_y) { 219 220 if (img.width > image_x) { 221 width = image_x; 222 ratio = image_x / img.width; 223 height = Math.round(img.height * ratio); 224 } 225 226 if (height > image_y) { 227 height = image_y; 228 ratio = image_y / img.height; 229 width = Math.round(img.width * ratio); 230 } 231 } else { 232 width = img.width; 233 height = img.height; 234 } 235 var canvas = $("<canvas/>").get(0); 236 canvas.width = width; 237 canvas.height = height; 238 var context = canvas.getContext('2d'); 239 context.drawImage(img, 0, 0, width, height); 240 var resizedImage = restoreExif(imageData, canvas.toDataURL('image/jpeg')); 241 blobImage = dataURItoBlob(resizedImage); 242 sendData.data.append('data', blobImage, file.name); 243 $.ajax(sendData); 244 } 245 246 } else { 247 sendData.data.append('data', file); 248 } 249 } else { 250 data = e.target.result; 251 sendData.data = { 252 name: file.name, 253 size: file.size, 254 type: file.type, 255 title: title, 256 data: data.substr(data.indexOf('base64') + 7), 257 galleryId: galleryId, 258 image_max_size_x: image_max_size_x, 259 image_max_size_y: image_max_size_y 260 }; 261 } 262 263 if (accept) { 264 valid = file.type.match(new RegExp(".?(" + accept.replace('*', '.*') + ")$", "i")); 265 } 266 267 if (valid && !waiting) { 268 $.ajax(sendData); 269 } else { 270 if (!valid) { 271 sendData.error(null); 272 } 273 } 274 };
275 reader.readAsDataURL(file); 276 }); 277 }); 278 $(window).dequeue('process-upload'); 279 }; 280 281 $(document).on('submit', 'form.file-uploader', function (e) { 282 e.preventDefault(); 283 }); 284 285 function doUpload($form, files) { 286 var progress, list, title = ""; 287 288 progress = new ProgressBar({ 289 progress: function (current, total) { 290 var percentage = Math.round(current / total * 100); 291 292 $form.find('.progress').removeClass("invisible"); 293 $form.find('.progress-bar') 294 .attr('aria-valuenow', percentage) 295 .width(percentage + '%'); 296 $form.find('.progress-bar .sr-only .count') 297 .text(percentage); 298 }, 299 done: function () { 300 $form.find('.progress').addClass("invisible"); 301 $form.find('.progress-bar') 302 .attr('aria-valuenow', 0) 303 .width('0%'); 304 $form.find('.progress-bar .sr-only .count') 305 .text('0%'); 306 // Clear required title in preparation for next file 307 $('.custom-file-title-input', $form).val(''); 308 } 309 }); 310 311 list = new FileList({ 312 list: $form.parent().find('.file-uploader-result ul')[0] 313 }); 314 315 list.clearErrors(); 316 317 if ($form.find('.custom-file-title-input').length) { 318 title = $form.find('.custom-file-title-input').val(); 319 } 320 321 handleFiles({ 322 accept: $form.find(':file').attr('accept'), 323 galleryId: $form.data('gallery-id'), 324 title: title, 325 ticket: $form.data('ticket'), 326 image_max_size_x:$form.data('image_max_size_x'), 327 image_max_size_y:$form.data('image_max_size_y'), 328 files: files, 329 progress: progress, 330 list: list, 331 form: $form 332 }); 333 } 334 335 function validateTitleProvided(form) { 336 if ($('.custom-file-title', form).is(':visible')) { 337 if (!$('.custom-file-title-input', form).val()) { 338 $('.custom-file-title .feedback-required-title', form).show(); 339 $('.custom-file-label', form).text('Choose file'); 340 form.trigger('reset'); 341 return false; 342 } else { 343 $('.custom-file-title .feedback-required-title', form).hide(); 344 return true; 345 } 346 } 347 return true; 348 } 349 350 function validateOneAtTime(form, files) { 351 if ($('.custom-file-title', form).is(':visible')) { 352 if (files.length > 1) { 353 $('.custom-file-title .feedback-one-at-time', form).show(); 354 $('.custom-file-label', form).text('Choose file'); 355 form.trigger('reset'); 356 return false; 357 } else { 358 $('.custom-file-title .feedback-one-at-time', form).hide(); 359 return true; 360 } 361 } 362 return true; 363 } 364 365 $(document).on('change', '.file-uploader input[type=file]', function () { 366 367 var $clone, $form = $(this).closest("form"), progress, list; 368 if (this.files) { 369 if (!validateTitleProvided($form)) { 370 return false; 371 } 372 if (!validateOneAtTime($form, this.files)) { 373 return false; 374 } 375 376 let $inlineDiv = $(this).parents(".file-uploader.inline"); 377 378 if ($inlineDiv.length) { 379 doUpload($inlineDiv, this.files); 380 } else { 381 doUpload($form, this.files); 382 } 383 384 $(this).val(''); 385 $clone = $(this).clone(true); 386 $(this).replaceWith($clone); 387 } 388 }); 389 390 if (window.FileReader) { 391 $(document).ready(function () { 392 $('.drop-message').show(); 393 }); 394 $(document).on('dragenter', '.file-uploader', function (e) { 395 e.preventDefault(); 396 e.stopPropagation(); 397 $(this).addClass("active"); 398 return false;
399 }); 400 $(document).on('dragexit dragleave', '.file-uploader', function (e) { 401 e.preventDefault(); 402 e.stopPropagation(); 403 $(this).removeClass("active"); 404 return false; 405 }); 406 $(document).on('dragover', '.file-uploader', function (e) { 407 e.preventDefault(); 408 e.stopPropagation(); 409 return false; 410 }); 411 $(document).on('drop', '.file-uploader', function (e) { 412 var $form = $(this); 413 414 if (!validateTitleProvided($form)) { 415 return false; 416 } 417 418 e.preventDefault(); 419 e.stopPropagation(); 420 $(this).removeClass("active"); 421 422 var dataTransfer = e.dataTransfer; 423 if (! dataTransfer) { 424 dataTransfer = e.originalEvent.dataTransfer; 425 } 426 427 if (dataTransfer && dataTransfer.files) { 428 if (!validateOneAtTime($form, dataTransfer.files)) { 429 return false; 430 } 431 doUpload($form, dataTransfer.files); 432 } 433 return false; 434 }); 435 } 436 437 function browserRemoveFile(link) 438 { 439 var list = $(link).closest('ul'); 440 $(link).closest('li').remove(); 441 442 list.closest('.file-browser').trigger('selection-update'); 443 } 444 445 function browserAddFile(link) 446 { 447 var content = $(link).closest('.media-body').clone(true), 448 icon = $(link).closest('.media, .panel').find('.media-object, .panel-body a').children('img').clone(true).width('16px'), 449 nav = $(link).closest('.file-browser').find('.selection ul'), 450 item = $('<li>'), 451 a = $('<a>').text($(link).text()), 452 id = $(link).data('object'), 453 limit = nav.closest('form').data('limit'), 454 current = nav.find('input[type=hidden]').filter(function () { 455 return parseInt($(this).val(), 10) === id; 456 }); 457 458 if (current.length > 0) { 459 // Already in the list 460 browserRemoveFile(current[0]); 461 return; 462 } 463 464 if (limit === 1) { 465 nav.empty(); 466 } else if (limit && nav.children('li').length >= limit) { 467 alert(nav.closest('form').data('limit-reached-message')); 468 return; 469 } 470 471 a 472 .prepend(' ') 473 .prepend(icon); 474 item.append(a); 475 nav.append(item); 476 477 item.append($('<input type="hidden" name="file[]">') 478 .attr('value', id)); 479 480 nav.closest('.file-browser').trigger('selection-update'); 481 } 482 483 $(document).on('selection-update', '.file-browser', function (e) { 484 var selection = $('.selection input[type=hidden]', this).map(function () { 485 return parseInt($(this).val(), 10); 486 }); 487 488 $('.gallery-list .media-heading a, .gallery-list .panel-body a', this).each(function () { 489 var id = $(this).data('object'); 490 $(this).closest('.media').toggleClass('bg-info', -1 !== $.inArray(id, selection)); 491 $(this).closest('.panel').toggleClass('panel-info', -1 !== $.inArray(id, selection)); 492 }); 493 $('.selection', this).toggleClass("invisible", selection.length === 0); 494 }); 495 496 $(document).on('click', '.file-browser .gallery-list .pagination a', function (e) { 497 e.preventDefault(); 498 $(this).closest('.modal').animate({ scrollTop: 0 }, 'slow'); 499 $(this).closest('.gallery-list') 500 .tikiModal(tr('Loading...')) 501 .load($(this).attr('href'), function () { 502 $(this).tikiModal(''); 503 $(this).closest('.file-browser').trigger('selection-update'); 504 }); 505 }); 506 507 $(document).on('click', '.file-browser .gallery-list .media-heading a, .file-browser .gallery-list .panel-body a', function (e) { 508 e.preventDefault(); 509 e.stopPropagation(); 510 browserAddFile(this); 511 }); 512 $(document).on('click', '.file-browser .gallery-list .media, .file-browser .gallery-list .panel', function (e) { 513 e.preventDefault(); 514 $('.media-heading a, .panel-body a', this).click(); 515 }); 516 517 $(document).on('click', '.file-browser .selection a', function (e) { 518 e.preventDefault(); 519 browserRemoveFile(this); 520 }); 521 522 $(document).on('submit', '.file-browser .form-inline', function (e) { 523 e.preventDefault(); 524 $(this).closest('.file-browser').find('.gallery-list') 525 .tikiModal(tr('Loading...')) 526 .load($(this).attr('action'), $(this).serialize(), function () { 527 $(this).tikiModal(''); 528 $(this).closest('.file-browser').trigger('selection-update'); 529 }); 530 }); 531 532 $(document).on('click', '.file-browser .submit .upload-files', function (e) { 533 var $list = $(this).closest('.file-browser').find('.selection ul'), 534 handler = $.clickModal({ 535 success: function (data) { 536 $.each(data.files, function (k, file) { 537 $('<li>') 538 .append($('<a href="#">') 539 .data('object', file.fileId)
540 .data('type', 'file') 541 .text(file.label)) 542 .append($('<input type="hidden" name="file[]">') 543 .attr('value', file.fileId)) 544 .appendTo($list); 545 546 $list.closest('.file-browser').trigger('selection-update'); 547 }); 548 $.closeModal(); 549 } 550 }); 551 552 handler.apply(this, arguments); 553 }); 554 555 // File selector component 556 $(document).on('click', '.file-selector a', function () { 557 if (! $(this).data('initial-href')) { 558 $(this).data('initial-href', $(this).attr('href')); 559 } 560 561 // Before the dialog handler triggers, replace the href with one including current files 562 $(this).attr('href', $(this).data('initial-href') + '&file=' + $(this).parent().children('input').val()); 563 }); 564 $(document).on('click', '.file-selector a', $.clickModal({ 565 size: 'modal-lg', 566 success: function (data) { 567 var files = []; 568 $.each(data.files, function (k, f) { 569 files.push(f.fileId); 570 }); 571 $(this).parent().children('input').val(files.join(',')); 572 $(this).text($(this).text().replace(/\d+/, files.length)); 573 $.closeModal(); 574 } 575 })); 576})(jQuery); 577 578function dataURItoBlob(dataURI) { 579 580 581 // convert base64/URLEncoded data component to raw binary data held in a string 582 var byteString; 583 if (dataURI.split(',')[0].indexOf('base64') >= 0) { 584 byteString = atob(dataURI.split(',')[1]); 585 } else { 586 byteString = unescape(dataURI.split(',')[1]); 587 } 588 589 // write the bytes of the string to a typed array 590 var ia = new Uint8Array(byteString.length); 591 for (var i = 0; i < byteString.length; i++) { 592 ia[i] = byteString.charCodeAt(i); 593 } 594 595 return new Blob([ia],{ type:'image/jpeg' }); 596} 597 598/* To minify a jpeg image without loosing EXIF. 599 * TESTED(24/01/2013): FireFox, GoogleChrome, IE10, Opera 600 * Copyright (c) 2013 hMatoba 601 * Released under the MIT license : https://github.com/hMatoba/MinifyJpegAsync/blob/master/LICENSE.txt 602 * 603 * To minify jpeg image: 604 * minified = MinifyJpeg.minify(image, length); 605 * xhr.send(minified.buffer); 606 * enc = "data:image/jpeg;base64," + MinifyJpeg.encode64(minified); 607 * html = '<img src="' + enc + '">'; 608 * MinifyJpeg.minify() - return Uint8Array 609 * image - image base64encoded, it can be obtained "FileReader().readAsDataURL(f)" 610 * length - the long side length of the rectangle 611 * MinifyJpeg.encode64() - convert array to base64encoded string 612 */ 613var MinifyJpeg = (function () { 614 615 var that = {}; 616 617 that.KEY_STR = "ABCDEFGHIJKLMNOP" + 618 "QRSTUVWXYZabcdef" + 619 "ghijklmnopqrstuv" + 620 "wxyz0123456789+/" + 621 "="; 622 623 that.SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207]; 624 625 that.minify = function (image, new_size) { 626 var newImage, rawImage; 627 628 if (image instanceof ArrayBuffer) { 629 if (image[0] == 255 && image[1] == 216) { 630 rawImage = []; 631 for (var i = 0; i < image.byteLength; i++) { 632 rawImage[i] = image[i]; 633 } 634 } 635 else { 636 throw "MinifyJpeg.minify got a not JPEG data"; 637 } 638 } 639 else { 640 if (typeof(image) === "string") { 641 if (!image.match("data:image/jpeg;base64,")) { 642 throw "MinifyJpeg.minify got a not JPEG data"; 643 } 644 else { 645 rawImage = that.decode64(image.replace("data:image/jpeg;base64,", "")); 646 } 647 } 648 else { 649 throw "First argument must be 'DataURL string' or ArrayBuffer."; 650 } 651 } 652 653 var segments = that.slice2Segments(rawImage); 654 var NEW_SIZE = parseInt(new_size); 655 var size = that.imageSizeFromSegments(segments); 656 var chouhen = (size[0] >= size[1]) ? size[0] : size[1]; 657 if (chouhen < NEW_SIZE) { 658 return new Uint8Array(rawImage); 659 } 660 661 var exif = that.getExif(segments); 662 var resized = that.resizeImage(rawImage, segments, NEW_SIZE); 663 664 if (exif.length) { 665 newImage = that.insertExif(resized, exif); 666 } 667 else { 668 newImage = new Uint8Array(that.decode64(resized.replace("data:image/jpeg;base64,", ""))); 669 } 670 671 return newImage; 672 }; 673 674 that.getImageSize = function (imageArray) { 675 var segments = that.slice2Segments(imageArray); 676 return that.imageSizeFromSegments(segments); 677 }; 678 679 that.slice2Segments = function (rawImageArray) { 680 var head = 0, 681 segments = []; 682 683 while (1) { 684 if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218) { 685 break; 686 } 687 if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216) { 688 head += 2; 689 } 690 else { 691 var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3], 692 endPoint = head + length + 2, 693 seg = rawImageArray.slice(head, endPoint); 694 segments.push(seg); 695 head = endPoint; 696 } 697 if (head > rawImageArray.length) { 698 break; 699 } 700 } 701 702 return segments; 703 }; 704 705 that.imageSizeFromSegments = function (segments) { 706 for (var x = 0; x < segments.length; x++) { 707 var seg = segments[x]; 708 if (that.SOF.indexOf(seg[1]) >= 0) { 709 var height = seg[5] * 256 + seg[6], 710 width = seg[7] * 256 + seg[8]; 711 break; 712 } 713 } 714 return [width, height]; 715 }; 716 717 that.encode64 = function (input) { 718 var output = "", 719 chr1, chr2, chr3 = "", 720 enc1, enc2, enc3, enc4 = "", 721 i = 0; 722 723 do {
724 chr1 = input[i++]; 725 chr2 = input[i++]; 726 chr3 = input[i++]; 727 728 enc1 = chr1 >> 2; 729 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 730 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 731 enc4 = chr3 & 63; 732 733 if (isNaN(chr2)) { 734 enc3 = enc4 = 64; 735 } else { 736 if (isNaN(chr3)) { 737 enc4 = 64; 738 } 739 } 740 741 output += that.KEY_STR.charAt(enc1) + 742 that.KEY_STR.charAt(enc2) + 743 that.KEY_STR.charAt(enc3) + 744 that.KEY_STR.charAt(enc4); 745 chr1 = chr2 = chr3 = ""; 746 enc1 = enc2 = enc3 = enc4 = ""; 747 } while (i < input.length); 748 return output; 749 }; 750 751 that.decode64 = function (input) { 752 var chr1, chr2, chr3 = "", 753 enc1, enc2, enc3, enc4 = "", 754 i = 0, 755 buf = []; 756 757 // remove all characters that are not A-Z, a-z, 0-9, +, /, or = 758 var base64test = /[^A-Za-z0-9\+\/\=]/g; 759 if (base64test.exec(input)) { 760 alert("There were invalid base64 characters in the input text.\n" + 761 "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" + 762 "Expect errors in decoding."); 763 } 764 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 765 766 do { 767 enc1 = that.KEY_STR.indexOf(input.charAt(i++)); 768 enc2 = that.KEY_STR.indexOf(input.charAt(i++)); 769 enc3 = that.KEY_STR.indexOf(input.charAt(i++)); 770 enc4 = that.KEY_STR.indexOf(input.charAt(i++)); 771 772 chr1 = (enc1 << 2) | (enc2 >> 4); 773 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 774 chr3 = ((enc3 & 3) << 6) | enc4; 775 776 buf.push(chr1); 777 778 if (enc3 != 64) { 779 buf.push(chr2); 780 } 781 if (enc4 != 64) { 782 buf.push(chr3); 783 } 784 785 chr1 = chr2 = chr3 = ""; 786 enc1 = enc2 = enc3 = enc4 = ""; 787 788 } while (i < input.length); 789 790 return buf; 791 }; 792 793 that.resizeImage = function (rawImage, segments, NEW_SIZE) { 794 var jpe, ctx, srcImg; 795 var size = that.imageSizeFromSegments(segments), 796 width = size[0], 797 height = size[1], 798 chouhen = (width >= height) ? width : height, 799 newSize = NEW_SIZE, 800 resizing = 1, 801 scale = parseFloat(newSize) / chouhen, 802 newWidth = parseInt(parseFloat(newSize) / chouhen * width), 803 newHeight = parseInt(parseFloat(newSize) / chouhen * height); 804 805 if (resizing == 1) // bilinear 806 { 807 var canvas = document.createElement('canvas'); 808 canvas.width = width; 809 canvas.height = height; 810 811 jpe = new JpegImage(); 812 ctx = canvas.getContext("2d"); 813 srcImg = ctx.getImageData(0, 0, width, height); 814 jpe.parse(new Uint8Array(rawImage)); 815 jpe.copyToImageData(srcImg); 816 817 var newCanvas = document.createElement('canvas'); 818 newCanvas.width = newWidth; 819 newCanvas.height = newHeight; 820 var newCtx = newCanvas.getContext("2d"); 821 var destImg = newCtx.createImageData(newWidth, newHeight); 822 that.bilinear(srcImg, destImg, scale); 823 824 newCtx.putImageData(destImg, 0, 0); 825 var resizedImage = newCanvas.toDataURL("image/jpeg"); 826 } 827 else // nearest neighbor? 828 { 829 canvas = document.createElement('canvas'); 830 canvas.width = newWidth; 831 canvas.height = newHeight; 832 833 jpe = new JpegImage(); 834 ctx = canvas.getContext("2d"); 835 d = ctx.getImageData(0, 0, newWidth, newHeight); 836 jpe.parse(new Uint8Array(rawImage)); 837 jpe.copyToImageData(d); 838 ctx.putImageData(d, 0, 0); 839 840 resizedImage = canvas.toDataURL("image/jpeg"); 841 } 842 843 return resizedImage; 844 }; 845 846 that.getExif = function (segments) { 847 var seg; 848 for (var x = 0; x < segments.length; x++) { 849 seg = segments[x]; 850 if (seg[0] == 255 & seg[1] == 225) //(ff e1) 851 { 852 return seg; 853 } 854 } 855 return []; 856 }; 857 858 that.insertExif = function (imageStr, exifArray) { 859 var buf = that.decode64(imageStr.replace("data:image/jpeg;base64,", "")), 860 separatePoint = buf.indexOf(255, 3), 861 mae = buf.slice(0, separatePoint), 862 ato = buf.slice(separatePoint), 863 array = mae.concat(exifArray, ato); 864 865 aBuffer = new Uint8Array(array); 866 867 return aBuffer; 868 }; 869 870 // compute vector index from matrix one 871 that.ivect = function (ix, iy, w) { 872 // byte array, r,g,b,a 873 return ((ix + w * iy) * 4); 874 }; 875 876 that.bilinear = function (srcImg, destImg, scale) { 877 // c.f.: wikipedia english article on bilinear interpolation 878 //log.debug("in bilinear"); 879 // taking the unit square 880 function inner(f00, f10, f01, f11, x, y) 881 { 882 var un_x = 1.0 - x; 883 var un_y = 1.0 - y; 884 return (f00 * un_x * un_y + f10 * x * un_y + f01 * un_x * y + f11 * x * y); 885 } 886 887 var srcWidth = srcImg.width;
888 var srcHeight = srcImg.height; 889 var srcData = srcImg.data; 890 var dstData = destImg.data; 891 var i, j; 892 var iyv, iy0, iy1, ixv, ix0, ix1; 893 var idxD, idxS00, idxS10, idxS01, idxS11; 894 var dx, dy; 895 for (i = 0; i < destImg.height; ++i) { 896 iyv = (i + 0.5) / scale - 0.5; 897 iy0 = Math.floor(iyv); 898 iy1 = (Math.ceil(iyv) > (srcHeight - 1) ? (srcHeight - 1) : Math.ceil(iyv)); 899 for (j = 0; j < destImg.width; ++j) { 900 ixv = (j + 0.5) / scale - 0.5; 901 ix0 = Math.floor(ixv); 902 ix1 = (Math.ceil(ixv) > (srcWidth - 1) ? (srcWidth - 1) : Math.ceil(ixv)); 903 idxD = that.ivect(j, i, destImg.width); 904 idxS00 = that.ivect(ix0, iy0, srcWidth); 905 idxS10 = that.ivect(ix1, iy0, srcWidth); 906 idxS01 = that.ivect(ix0, iy1, srcWidth); 907 idxS11 = that.ivect(ix1, iy1, srcWidth); 908 // log.debug(sprintf("bilinear: idx: D: %d, S00: %d, S10: %d, S01: %d, S11: %d", idxD, idxS00, idxS10, 909 // idxS01, idxS11)); 910 dx = ixv - ix0; 911 dy = iyv - iy0; 912 913 //r 914 dstData[idxD] = inner(srcData[idxS00], srcData[idxS10], 915 srcData[idxS01], srcData[idxS11], dx, dy 916 ); 917 918 //g 919 dstData[idxD + 1] = inner(srcData[idxS00 + 1], srcData[idxS10 + 1], 920 srcData[idxS01 + 1], srcData[idxS11 + 1], dx, dy 921 ); 922 923 //b 924 dstData[idxD + 2] = inner(srcData[idxS00 + 2], srcData[idxS10 + 2], 925 srcData[idxS01 + 2], srcData[idxS11 + 2], dx, dy 926 ); 927 928 //a 929 dstData[idxD + 3] = inner(srcData[idxS00 + 3], srcData[idxS10 + 3], 930 srcData[idxS01 + 3], srcData[idxS11 + 3], dx, dy 931 ); 932 } 933 } 934 }; 935 return that; 936})(); 937 938function processFgalSyntax(fileInfo, theSyntax) { 939 var key, part, syntax = ""; 940 if (typeof fileInfo === "string") { 941 fileInfo = JSON.parse(fileInfo); 942 } 943 syntax = syntax ? decodeURIComponent(syntax[1]) : (theSyntax || fileInfo.syntax || fileInfo.wiki_syntax); 944 for (key in fileInfo) { 945 if (fileInfo.hasOwnProperty(key)) { 946 part = "{" + key + "}"; 947 if (syntax.indexOf(part) > -1) { 948 syntax = syntax.replace(part, fileInfo[key]); 949 } 950 } 951 } 952 return syntax; 953}
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.