Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: add support for single upload field deletion, multifile upload f… #24

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions gravityforms-multiple-form-instances.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class Gravity_Forms_Multiple_Form_Instances {
public function __construct() {
// hook the HTML ID string find & replace functionality
add_filter( 'gform_get_form_filter', array( $this, 'gform_get_form_filter' ), 10, 2 );
// hook the multifile upload script replace functionality
add_filter( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}

/**
Expand Down Expand Up @@ -95,6 +97,14 @@ public function gform_get_form_filter( $form_string, $form ) {
'GFCalc(' . $form['id'] . ',' => 'GFCalc(' . $random_id . ',',
'gf_global["number_formats"][' . $form['id'] . ']' => 'gf_global["number_formats"][' . $random_id . ']',
'gform_next_button_' . $form['id'] . '_' => 'gform_next_button_' . $random_id . '_',
'multipart_params":{"form_id"' => 'multipart_params":{"random_id":' . $random_id . ',"form_id"',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we add the 'random_id' multipart_param, that is then simply accessible in the code, since plupload will have a reference to it in its 'settings.multipart_params.random_id' property.
The drawback is that it is also sent to the server while uploading files, and doesn't have any purpose in this context.

'gform_multifile_upload_' . $form['id'] . '_' => 'gform_multifile_upload_' . $random_id . '_',
'gform_drag_drop_area_' . $form['id'] . '_' => 'gform_drag_drop_area_' . $random_id . '_',
'gform_browse_button_' . $form['id'] . '_' => 'gform_browse_button_' . $random_id . '_',
'gform_preview_' . $form['id'] . '_' => 'gform_preview_' . $random_id . '_',
'gform_multifile_messages_' . $form['id'] . '_' => 'gform_multifile_messages_' . $random_id . '_',
'gform_uploaded_files_' . $form['id'] => 'gform_uploaded_files_' . $random_id,
'gformDeleteUploadedFile(' . $form['id'] . ',' => 'gformDeleteUploadedFile(' . $random_id . ',',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support for single upload field file deletion.

$hidden_field => "<input type='hidden' name='gform_random_id' value='" . $random_id . "' />" . $hidden_field,
);

Expand All @@ -109,6 +119,17 @@ public function gform_get_form_filter( $form_string, $form ) {
return $form_string;
}

/**
* Enqueues the multifile upload script in wordpress scripts.
*
* @access public
*
* @return void
*/
public function enqueue_scripts() {
wp_enqueue_script( 'gform_mfi_multifile', plugin_dir_url( __FILE__ ) . 'js/gravityforms-mfi-multifile.js', array( 'jquery', 'gform_gravityforms' ) );
}

}

// initialize the plugin
Expand Down
290 changes: 290 additions & 0 deletions js/gravityforms-mfi-multifile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
/*
Copyright 2009-2016 Rocketgenius, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses.
*/

//----------------------------------------
//------ MULTIFILE UPLOAD FUNCTIONS ------
//----------------------------------------

(function (gfMultiFileUploader, $) {
gfMultiFileUploader.uploaders = {};
var strings = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.strings : {};
var imagesUrl = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.vars.images_url : "";

$(document).unbind('gform_post_render');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we unbind the original gravity forms setup function hooked to the document's 'gform_post_render' function.
The fact that this script depends on 'gform_gravityforms' script (cf. https://github.com/tyxla/Gravity-Forms-Multiple-Form-Instances/pull/24/files#diff-7d573d66d37a99e5734d905449d49972R130), ensures that the unbind will be properly executed after the original binding has been done.

$(document).bind('gform_post_render', function(e, formID){
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we bind our function, that will call copies of our original gravityforms functions, but they will use the random form id instead of the original (see next comment).

Copy link
Contributor Author

@medfreeman medfreeman Jan 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since everything is in a closure on the original file, it is not possible to call the original functions instead, not being referenced in any accessible javascript variable.


$("form#gform_" + formID + " .gform_fileupload_multifile").each(function(){
setup(this);
});
var $form = $("form#gform_" + formID);
if($form.length > 0){
$form.submit(function(){
var pendingUploads = false;
$.each(gfMultiFileUploader.uploaders, function(i, uploader){
if(uploader.total.queued>0){
pendingUploads = true;
return false;
}
});
if(pendingUploads){
alert(strings.currently_uploading);
window["gf_submitting_" + formID] = false;
$('#gform_ajax_spinner_' + formID).remove();
return false;
}
});
}

});

gfMultiFileUploader.setup = function (uploadElement){
setup( uploadElement );
};

function setup(uploadElement){
var settings = $(uploadElement).data('settings');

var uploader = new plupload.Uploader(settings);
formID = uploader.settings.multipart_params.random_id;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we assign the formID used througout this file to the form's random id, injected here (https://github.com/tyxla/Gravity-Forms-Multiple-Form-Instances/pull/24/files#diff-7d573d66d37a99e5734d905449d49972R100) into the multifile upload field multipart_param.
It could also be added to another attribute, to avoid sending the value to the server while adding files, but i let it this way to simplify the code.

gfMultiFileUploader.uploaders[settings.container] = uploader;
var formID;
var uniqueID;

uploader.bind('Init', function(up, params) {
if(!up.features.dragdrop)
$(".gform_drop_instructions").hide();
var fieldID = up.settings.multipart_params.field_id;
var maxFiles = parseInt(up.settings.gf_vars.max_files);
var initFileCount = countFiles(fieldID);
if(maxFiles > 0 && initFileCount >= maxFiles){
gfMultiFileUploader.toggleDisabled(up.settings, true);
}

});

gfMultiFileUploader.toggleDisabled = function (settings, disabled){

var button = typeof settings.browse_button == "string" ? $("#" + settings.browse_button) : $(settings.browse_button);
button.prop("disabled", disabled);
};

function addMessage(messagesID, message){
$("#" + messagesID).prepend("<li>" + message + "</li>");
}

uploader.init();

uploader.bind('FilesAdded', function(up, files) {
var max = parseInt(up.settings.gf_vars.max_files),
fieldID = up.settings.multipart_params.field_id,
totalCount = countFiles(fieldID),
disallowed = up.settings.gf_vars.disallowed_extensions,
extension;

if( max > 0 && totalCount >= max){
$.each(files, function(i, file) {
up.removeFile(file);
return;
});
return;
}
$.each(files, function(i, file) {

extension = file.name.split('.').pop();

if($.inArray(extension, disallowed) > -1){
addMessage(up.settings.gf_vars.message_id, file.name + " - " + strings.illegal_extension);
up.removeFile(file);
return;
}

if ((file.status == plupload.FAILED) || (max > 0 && totalCount >= max)){
up.removeFile(file);
return;
}

var size = typeof file.size !== 'undefined' ? plupload.formatSize(file.size) : strings.in_progress;
var status = '<div id="'
+ file.id
+ '" class="ginput_preview">'
+ file.name
+ ' (' + size + ') <b></b> '
+ '<a href="javascript:void(0)" title="' + strings.cancel_upload + '" onclick=\'$this=jQuery(this); var uploader = gfMultiFileUploader.uploaders.' + up.settings.container + ';uploader.stop();uploader.removeFile(uploader.getFile("' + file.id +'"));$this.after("' + strings.cancelled + '"); uploader.start();$this.remove();\' onkeypress=\'$this=jQuery(this); var uploader = gfMultiFileUploader.uploaders.' + up.settings.container + ';uploader.stop();uploader.removeFile(uploader.getFile("' + file.id +'"));$this.after("' + strings.cancelled + '"); uploader.start();$this.remove();\'>' + strings.cancel + '</a>'
+ '</div>';

$('#' + up.settings.filelist).prepend(status);
totalCount++;

});

up.refresh(); // Reposition Flash

var formElementID = "form#gform_" + formID;
var uidElementID = "input:hidden[name='gform_unique_id']";
var uidSelector = formElementID + " " + uidElementID;
var $uid = $(uidSelector);
if($uid.length==0){
$uid = $(uidElementID);
}

uniqueID = $uid.val();
if('' === uniqueID){
uniqueID = generateUniqueID();
$uid.val(uniqueID);
}


if(max > 0 && totalCount >= max){
gfMultiFileUploader.toggleDisabled(up.settings, true);
addMessage(up.settings.gf_vars.message_id, strings.max_reached)
}


up.settings.multipart_params.gform_unique_id = uniqueID;
up.start();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since gravity's php code processing file uploads has no relevant hooks to allow modyfing the submitting form id, and that an upload referencing the random form id will fail, the upload process is strictly the same as without this plugin.
The multipart_param 'form_id' parameter is not modified, so the server receives the original form id, and processes the upload properly.


});

uploader.bind('UploadProgress', function(up, file) {
var html = file.percent + "%";
$('#' + file.id + " b").html(html);
});

uploader.bind('Error', function(up, err) {
if(err.code === plupload.FILE_EXTENSION_ERROR){
var extensions = typeof up.settings.filters.mime_types != 'undefined' ? up.settings.filters.mime_types[0].extensions /* plupoad 2 */ : up.settings.filters[0].extensions;
addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.invalid_file_extension + " " + extensions);
} else if (err.code === plupload.FILE_SIZE_ERROR) {
addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.file_exceeds_limit);
} else {
var m = "<li>Error: " + err.code +
", Message: " + err.message +
(err.file ? ", File: " + err.file.name : "") +
"</li>";

addMessage(up.settings.gf_vars.message_id, m);
}
$('#' + err.file.id ).html('');

up.refresh(); // Reposition Flash
});

uploader.bind('FileUploaded', function(up, file, result) {
var response = $.secureEvalJSON(result.response);
if(response.status == "error"){
addMessage(up.settings.gf_vars.message_id, file.name + " - " + response.error.message);
$('#' + file.id ).html('');
return;
}

var html = '<strong>' + file.name + '</strong>';
var formId = up.settings.multipart_params.random_id;
var fieldId = up.settings.multipart_params.field_id;
html = "<img "
+ "class='gform_delete' "
+ "src='" + imagesUrl + "/delete.png' "
+ "onclick='gformDeleteUploadedFile(" + formId + "," + fieldId + ", this);' "
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and on the next line, the formID is, as everywhere else, the random form id assigned by this plugin.
This allows proper deletion of the uploaded file.

+ "onkeypress='gformDeleteUploadedFile(" + formId + "," + fieldId + ", this);' "
+ "alt='"+ strings.delete_file + "' "
+ "title='" + strings.delete_file
+ "' /> "
+ html;

html = gform.applyFilters( 'gform_file_upload_markup', html, file, up, strings, imagesUrl );

$( '#' + file.id ).html( html );

var fieldID = up.settings.multipart_params["field_id"];

if(file.percent == 100){
if(response.status && response.status == 'ok'){
addFile(fieldID, response.data);
} else {
addMessage(up.settings.gf_vars.message_id, strings.unknown_error + ': ' + file.name);
}
}



});

function getAllFiles(){
var selector = '#gform_uploaded_files_' + formID,
$uploadedFiles = $(selector), files;

files = $uploadedFiles.val();
files = (typeof files === "undefined") || files === '' ? {} : $.parseJSON(files);

return files;
}


function getFiles(fieldID){
var allFiles = getAllFiles();
var inputName = getInputName(fieldID);

if(typeof allFiles[inputName] == 'undefined')
allFiles[inputName] = [];
return allFiles[inputName];
}

function countFiles(fieldID){
var files = getFiles(fieldID);
return files.length;
}

function addFile(fieldID, fileInfo){

var files = getFiles(fieldID);

files.unshift(fileInfo);
setUploadedFiles(fieldID, files);
}

function setUploadedFiles(fieldID, files){
var allFiles = getAllFiles();
var $uploadedFiles = $('#gform_uploaded_files_' + formID);
var inputName = getInputName(fieldID);
allFiles[inputName] = files;
$uploadedFiles.val($.toJSON(allFiles));
}

function getInputName(fieldID){
return "input_" + fieldID;
}

// fixes drag and drop in IE10
$("#" + settings.drop_element).on({
"dragenter": ignoreDrag,
"dragover": ignoreDrag
});

function ignoreDrag( e ) {
e.preventDefault();
}
}


function generateUniqueID() {
return 'xxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}


}(window.gfMultiFileUploader = window.gfMultiFileUploader || {}, jQuery));
Loading