/* -*- C++ -*- */ /** * Very hacky jquery plugin to handle uploading through iframes and drag/drop. * * $Id: upload.js 2231 2011-07-14 00:25:21Z max $ */ (function () { jQuery.fn.ytmnd_uploader = function(drop_box, options) { /** * input is a selector for a file input * drop_box is a div which files can be dragged to. */ var defaults = { "max_size": 12280000, "min_size": 0, "accepted_types": {"GIF": {"extensions": ["GIF"], "mime_types": ["image/gif"]}, "PNG": {"extensions": ["PNG"], "mime_types": ["image/png"]}, "JPG": {"extensions": ["JPG", "JPEG"], "mime_types": ["image/jpeg"]}, "MP3": {"extensions": ["MP3"], "mime_types": ["audio/mpeg", "audio/mp3"]}, "WAV": {"extensions": ["WAV"], "mime_types": ["audio/x-wav", "audio/wav"]}}, "post_url": "/assets/upload/file" }; var settings = jQuery.extend(defaults, options); //MARK verify input and drop_box exist and are of right type, etc. var uploader = function() { var file_input = jQuery(this); console.max('YTMND_UPLOADER CALLED on ', file_input); var upload_key = jQuery.md5('dongs' + Math.random()).substr(0,8); file_input.data('upload_key', upload_key); /** * Event handlers. */ /** * For the drop box */ var dragover = null; var dragenter = null; var drop = null; /** * For the file input */ var change = null; dragstart = function(event) { var file_uploader = event.data.upload_control; var data_transfer = event.originalEvent.dataTransfer; file_uploader.trigger('dragstart', [event, data_transfer]); if (typeof data_transfer != 'undefined' && typeof data_transfer.effectAllowed != 'undefined') { data_transfer.effectAllowed = 'copy'; data_transfer.dropEffect = 'copy'; } event.stopPropagation(); event.preventDefault(); }; dragover = function(event) { //console.max('jello from dragover', this); var file_uploader = event.data.upload_control; var data_transfer = event.originalEvent.dataTransfer; file_uploader.trigger('dragover', [event, data_transfer]); if (typeof data_transfer != 'undefined' && typeof data_transfer.effectAllowed != 'undefined') { data_transfer.dropEffect = 'copy'; //data_transfer.effectAllowed = 'copy'; } event.stopPropagation(); event.preventDefault(); }; dragenter = function(event) { //console.max('jello from dragenter', this); var file_uploader = event.data.upload_control; var data_transfer = event.originalEvent.dataTransfer; file_uploader.trigger('dragenter', [event, data_transfer]); event.stopPropagation(); event.preventDefault(); }; drop = function(event) { event.stopPropagation(); event.preventDefault(); console.max('jello from drop', this); var file_uploader = event.data.upload_control; var data_transfer = event.originalEvent.dataTransfer;; if (data_transfer.files.length > 1) { alert('Please only drag one file at a time!'); return false; } else if (data_transfer.files.length < 1) { alert('Please drag a file to upload!'); return false; } var dropped_file = data_transfer.files[0]; if (dropped_file.name === undefined && dropped_file.size === undefined) { dropped_file.name = dropped_file.fileName; dropped_file.size = dropped_file.fileSize; } /** * Check file size */ if (dropped_file.size < settings.min_size) { alert('File is smaller than the minimum size (' + settings.min_size + ' bytes)'); return false; } if (dropped_file.size > settings.max_size) { alert('File is larger than the maximum size (' + settings.max_size + ' bytes)'); return false; } /** * Check file type */ var acceptable_type = false; var file_types = []; for (var i in settings.accepted_types) { for (var j in settings.accepted_types[i].mime_types) { if (settings.accepted_types[i].mime_types[j] == dropped_file.type) { acceptable_type = true; break; } } file_types.push(i); } if (acceptable_type === false) { alert('This file is not currently accepted, please use one of the following: ' + file_types.join(', ')); //error 'File is not in the acceptable type list.' return false; } //drop [event, dropped_file] file_input.trigger('send_file', [event, dropped_file, this]); }; var change_file = function(event) { event.stopPropagation(); event.preventDefault(); var chosen_file = event.target.files; if (typeof chosen_file == 'undefined' || typeof chosen_file.length == 'undefined') { chosen_file = [{name: event.target.value.replace(/^.*\\/, '')}]; /** * Check file against list. */ var file_type = chosen_file[0].name.match(/\.([^\.]*)$/); if (file_type != null && typeof file_type[1] != 'undefined') { file_type = file_type[1].toLowerCase(); } else { file_type = ''; } var acceptable_type = false; var file_types = []; for (var i in settings.accepted_types) { for (var j in settings.accepted_types[i].extensions) { if (settings.accepted_types[i].extensions[j].toLowerCase() == file_type) { acceptable_type = true; break; } } file_types.push(i); } if (acceptable_type === false) { alert('This file is not currently accepted, please use one of the following: ' + file_types.join(', ')); //error 'File is not in the acceptable type list.' return false; } //alert('This file is not currently accepted, please use one of the following: ' + file_types.join(', ')); file_input.trigger('send_file_iframe', [event, chosen_file[0], this]); } else { file_input.trigger('send_file', [event, chosen_file[0], this]); } }; var send_file = function (event, original_event, file) { file_input.trigger('uploading', [file]); var form = jQuery(this).prop('form'); var input_name = jQuery(this).prop('name'); var post_url = settings.post_url || jQuery(form).prop('action'); var form_data = new FormData(); form_data.append("PHP_SESSION_UPLOAD_PROGRESS", upload_key); form_data.append("user", me.user_id); form_data.append("auth", me.auth_hash); form_data.append(input_name, file); /** * Set up ajax options */ var ajax_options = { "async": true, "cache": false, "data": form_data, "type": "POST", "url": post_url, "dataType": "json", "timeout": 300000, "processData": false, "contentType": false, "headers": {'X-File-Name': file.name, 'X-File-Type': file.type, 'X-File-Size': file.size}, }; ajax_options.success = function(){ file_input.trigger('upload_success', arguments); }; ajax_options.error = function(){ file_input.trigger('upload_error', arguments); }; ajax_options.complete = function(){ file_input.trigger('upload_complete', arguments); }; jQuery.ajax(post_url, ajax_options); } var send_file_iframe = function (event, original_event, file) { file_input.trigger('uploading', [file]); console.log('SENDING IFRAME'); var form = jQuery(this).prop('form'); var input_name = jQuery(this).prop('name'); var post_url = settings.post_url || jQuery(form).prop('action'); var ajax_options = { "async": true, "cache": false, "formData": [{name: "PHP_SESSION_UPLOAD_PROGRESS", value: upload_key}, {name: "user", value: me.user_id}, {name: "auth", value: me.auth_hash}], "type": "POST", "url": post_url, "dataType": "iframe json", "timeout": 300000, "fileInput": jQuery(this), "processData": false, "contentType": false, }; ajax_options.success = function(){ file_input.trigger('upload_success', arguments); }; ajax_options.error = function(){ file_input.trigger('upload_error', arguments); }; ajax_options.complete = function(){ alert('dong'); file_input.trigger('upload_complete', arguments); }; jQuery.ajax(post_url, ajax_options); } /** * Figure out if we can even drag/drop. */ var can_drag_drop = false; if (typeof File != 'undefined' && typeof Blob != 'undefined') {// && typeof DataTransfer != 'undefined') { can_drag_drop = true; } if (can_drag_drop == false) { jQuery(drop_box).hide(); } else { jQuery(drop_box).show(); } jQuery(drop_box).bind( 'dragstart' , {"upload_control": file_input}, dragstart); jQuery(drop_box).bind( 'dragover' , {"upload_control": file_input}, dragover); jQuery(drop_box).bind( 'dragenter' , {"upload_control": file_input}, dragenter); jQuery(drop_box).bind( 'drop' , {"upload_control": file_input}, drop); jQuery(file_input).bind('change' , {"upload_control": file_input}, change_file); jQuery(file_input).bind('send_file' , {"upload_control": file_input},send_file); jQuery(file_input).bind('send_file_iframe', {"upload_control": file_input},send_file_iframe); } if (this.length > 1) { //throw error } this.each(uploader); return this; }; /** * The rest of the upload widget */ $(document).ready(function(){ var upload_fields = $('.upload_widget_wrappers > .file > input[type="file"]'); /** * Toggles which piece of the form that shows up when their radio buttons are changed. */ $('.upload_widget_selector > input[name$="_type"]').click(function(event){ var widget_id = $(this).parent().data('widget_id'); var parent_div = null; $('.upload_widget_wrappers').each(function(){ if ($(this).data('widget_id') == widget_id) { parent_div = $(this); return false; } }); if (parent_div == null) { console.max('COULD NOT FIND WRAPPERS FOR ', this); return false; } switch($(this).val()) { case 'file': parent_div.children('.asset, .fetch, .generate, .default').hide(); parent_div.children('.file').show(); break; case 'fetch': parent_div.children('.file, .asset, .generate, .default').hide(); parent_div.children('.fetch').show(); break; case 'asset': parent_div.children('.file, .fetch, .generate, .default').hide(); parent_div.children('.asset').show(); break; case 'generate': parent_div.children('.file, .fetch, .asset, .default').hide(); parent_div.children('.generate').show(); break; case 'default': parent_div.children('.file, .fetch, .asset, .generate').hide(); parent_div.children('.default').show(); break; case 'none': parent_div.children('.asset, .fetch, .file, .generate, .default').hide(); break; } }); $('.upload_widget_selector > input[name$="_type"]:checked').click(); /** * Validates an asset ID over AJAX */ var check_asset = function() { console.max('EVENT: CHECK_ASSET in upload.js'); var asset_field = $(this); var asset_id = asset_field.val(); var asset_type = asset_field.data('asset_type'); var check_url = '/interface/check/asset/' + asset_id + '?type=' + asset_type; var actual_type = null; var handle_asset_data = function(data){ var status_div = asset_field.siblings('.asset_status'); var valid_div = status_div.children('.indicator'); var links_div = status_div.children('.links'); if (typeof data.error !== 'undefined') { valid_div.removeClass('green').addClass('red'); if (data.error == 'wrong_type') { valid_div.html('WRONG TYPE'); } else if (typeof data.preview != 'undefined' && data.preview.valid == false) { valid_div.html('INVALID PREVIEW'); } else { valid_div.html('UNKNOWN ERROR'); } } else if (data.exists == true) { valid_div.addClass('green').removeClass('red'); valid_div.html('VALID'); asset_field.data('valid_asset_id', true); } else if (data.exists == false) { valid_div.removeClass('green').addClass('red'); valid_div.html('INVALID'); asset_field.data('valid_asset_id', false); } if (typeof data.type != 'undefined') { actual_type = data.type; } if (typeof data.url != 'undefined') { var asset_links = ' [ '; asset_links += 'link - '; asset_links += 'info'; if (actual_type == 'image') { asset_links += ' - edit'; } asset_links += ' ] '; links_div.html(asset_links); } if (asset_type == 'preview') { var preview = data.preview; var error_msg = ''; var valid_specs = ''; valid_specs += 'Image size must be 420x300 or 1024x768. 420x300 images must be 35kb or less, \n'; valid_specs += '1024x768 images must be 160kb or less. GIF or JPG format is preferred, but PNG is \n'; valid_specs += 'accepted. Your preview image MUST be safe-for-work.\n '; if (preview.valid == false) { if (preview.reason == 'INVALID_SIZE') { error_msg = 'Your preview image size is invalid. '; } else if (preview.reason == 'FILE_TOO_BIG') { error_msg = 'Your preview image was too large to be accepted.'; } else if (preview.reason == 'DOESNT_EXIST' || preview.reason == 'BAD_INFO') { error_msg = 'We encountered an error resizing your preview image, it may be corrupt.'; } else if (preview.reason == 'NOT_IMAGE') { error_msg = 'The preview asset you provided is not one of our accepted image formats.'; } else { error_msg = 'An unknown error occurred, you may not use this image as a preview image.'; } asset_field.trigger('invalid_preview', [data, error_msg, valid_specs]); } else { ytmnd.sc.thumbnails.preview = preview.final_preview_asset_id; for (var size in preview.versions) { ytmnd.sc.thumbnails.previews[size] = preview.versions[size]; } asset_field.trigger('valid_preview', [data]); } } }; $.getJSON(check_url, handle_asset_data); }; $('.upload_widget_wrappers > .asset > input[type="text"]').bind('check_asset', check_asset); $('.upload_widget_wrappers > .asset > input[type="text"]').keydown(function(event){ if ((event.keyCode > 47 && event.keyCode < 90) || (event.keyCode > 96 && event.keyCode < 111)) { if (!!String.fromCharCode(event.keyCode).match(/[^0-9a-f]/i)) { event.preventDefault(); } } }); $('.upload_widget_wrappers > .asset > input[type="text"]').keyup(function(event){ var asset_input = $(this); var asset_id = asset_input.val(); if ($(this).val().match(/[^0-9a-f]/i) != null) { event.preventDefault(); $(this).val($(this).val().replace(/[^0-9a-f]/ig, '')); } if ((asset_id.match(/[a-f]+/) && asset_id.length != 32) || asset_id.trim() == '') { asset_input.siblings('.asset_status').children().html('').removeClass('red green'); asset_input.siblings('.asset_status').children('.indicator').addClass('red').html('INVALID ASSET ID'); return; } clearTimeout($(this).data('timer')); $(this).data('timer', setTimeout(function(){ asset_input.trigger('check_asset'); }, 250)); }).keyup(); /** * Event handling. * * uploading - the start of an upload. * upload_success - successful completion of the upload AJAX upload (there might still be errors) * upload_error - fired when an AJAX error occurs * upload_complete - fired off when an upload is totally complete regardless of failure. */ /** * Holds the timers for checking upload progress. */ var upload_timers = {}; /** * Event fired off at the start of an upload. */ upload_fields.bind('uploading', function(){ $(this).data('is_uploading', true); var upload_key = $(this).data('upload_key'); var widget_id = $(this).data('widget_id'); var progress_bar = $('