return $imageGallery;
}
+
+ /*
+ * Set gallery image positions
+ *
+ * Reads a submitted comma-delimited list of ID numbers creted by jQuery sortable()
+ * and updates the "position" field in the images table for those entries to be
+ * in the requested sequential order.
+ *
+ * @param int $refType Reference Type
+ * @param int $refID Reference entry ID
+ * @param string $orderField Name of SUBMIT field containing sort order.
+ *
+ * @return boolean True if successful
+ *
+ */
+ public function galleryPositionOrder($refType, $refID, $orderField)
+ {
+
+ // Check for and retrieve the order field name
+ if (isset($_REQUEST[$orderField]) && trim($_REQUEST[$orderField]) == '') {
+
+ if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) {
+ glmMembersAdmin::addNotice('<b>dataImages: </b>galleryPositionOrder() unable to find '.$orderField.'data.', 'Process');
+ }
+
+ return false;
+ }
+
+ // Break order out into an array
+ $order = explode(',', $_REQUEST[$orderField]);
+ if (count($order) == 0) {
+ return false;
+ }
+
+ if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) {
+ glmMembersAdmin::addNotice($order, 'DataBlock', 'Image Gallery Sort Order');
+ }
+
+ // Update image entries with new sort order;
+ $pos = 0;
+ foreach($order as $i) {
+ $sql = "UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images SET position = $pos WHERE id = $i;";
+ $this->wpdb->query($sql);
+ $pos++;
+
+ $queryError = $this->wpdb->last_error;
+ if ($queryError) {
+
+ if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) {
+ glmMembersAdmin::addNotice("<b> Error setting position order for images.</b><br>$queryError", 'Alert');
+ }
+
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ /*
+ * Process image gallery titles, decriptions, deletions, and image position ordering.
+ *
+ * @param int $refType Reference Type
+ * @param int $refID Reference entry ID
+ * @param string $orderField Name of SUBMIT field containing sort order.
+ *
+ * @return boolean True if successful
+ *
+ */
+ public function galleryImageDataUpdate($refType, $refID, $orderField)
+ {
+
+ // Re-order image gallery images
+ $this->galleryPositionOrder($refType, $refID, $orderField);
+
+ // Update text for title and descriptions
+ reset($_REQUEST['galleryImage_caption']);
+ while (list($k, $v) = each($_REQUEST['galleryImage_caption'])) {
+ $id = ($k -0);
+
+ // Sanitize input
+ $caption = sanitize_text_field( $_REQUEST['galleryImage_caption'][$k] );
+ $descr = sanitize_text_field( $_REQUEST['galleryImage_descr'][$k] );
+
+ // Update data for this image
+ $sql = "UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images SET caption = '$caption', descr = '$descr' WHERE id = $id;";
+ $this->wpdb->query($sql);
+
+ }
+
+ // Check for an image deletion
+ if (isset($_REQUEST['galleryImage_delete']) && count($_REQUEST['galleryImage_delete']) > 0) {
+
+ // For each delete selected
+ reset($_REQUEST['galleryImage_delete']);
+ while (list($k, $v) = each($_REQUEST['galleryImage_delete'])) {
+ $id = ($k -0);
+
+ // If a valid key and delete request is in fact set
+ if ($id > 0 && $v == 'on') {
+
+ // Get the data for this image
+ $sql = "SELECT * FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images WHERE id = $id;";
+ $imgData = $this->wpdb->get_row($sql, ARRAY_A);
+
+ // Do we have data?
+ if ($imgData != null && trim($imgData['file_name']) != '') {
+
+ // Delete the image from the gallery
+ $sql = "DELETE FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images WHERE id = $id;";
+ $this->wpdb->query($sql);
+
+ // Also delete all copies of the image
+ reset($this->config['imageSizes']);
+ while (list($k, $v) = each($this->config['imageSizes'])) {
+
+ if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) {
+ glmMembersAdmin::addNotice(" Deleting size $k.", 'Process');
+ }
+
+ // Delete each image size
+ unlink(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$k.'/'.$imgData['file_name']);
+
+ }
+
+ // Also delete the original
+ unlink(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/original/'.$imgData['file_name']);
+
+ }
+ }
+ }
+ }
+
+ // Get updated image gallery
+ $imageGallery = $this->getGallery($refType, $refID);
+ return $imageGallery;
+
+ }
+
}
?>
\ No newline at end of file
;
ref_type[0] = 'None'
ref_type[10] = 'Member'
-ref_type[20] = 'Location'
-ref_type[30] = 'Facility'
-ref_type[40] = 'Activity'
-ref_type[50] = 'Golf'
-ref_type[60] = 'Restaurant'
-ref_type[70] = 'Contact'
+ref_type[20] = 'MemberInfo'
+ref_type[30] = 'Location'
+ref_type[40] = 'Facility'
+ref_type[50] = 'Activity'
+ref_type[60] = 'Golf'
+ref_type[70] = 'Restaurant'
+ref_type[80] = 'Contact'
+
+ref_type_table[0] = ''
+ref_type_table[10] = 'members'
+ref_type_table[20] = 'member_info'
+ref_type_table[30] = 'locations'
+ref_type_table[40] = 'facilities'
+ref_type_table[50] = 'activities'
+ref_type_table[60] = 'golf'
+ref_type_table[70] = 'restaurants'
+ref_type_table[80] = 'contacts'
ref_type_numb['None'] = 0
ref_type_numb['Member'] = 10
-ref_type_numb['Location'] = 20
-ref_type_numb['Facility'] = 30
-ref_type_numb['Activity'] = 40
-ref_type_numb['Golf'] = 50
-ref_type_numb['Restaurant'] = 60
-ref_type_numb['Contact'] = 70
+ref_type_numb['MemberInfo'] = 20
+ref_type_numb['Location'] = 30
+ref_type_numb['Facility'] = 40
+ref_type_numb['Activity'] = 50
+ref_type_numb['Golf'] = 60
+ref_type_numb['Restaurant'] = 70
+ref_type_numb['Contact'] = 80
;
; Facility Type
*/
$GLOBALS['glmMembersAdminValidActions'] = array(
+ 'ajax' => array(
+ 'imageUpload'
+ ),
'dashboardWidget' => array(
'index'
),
'locations',
'facilities',
'activities',
- 'accommodations',
- 'memberImage', // Member Image Processing via AJAX
+ 'accommodations'
)
,
'configure' => array(
));
// Add AJAX image upload action
- add_action( 'wp_ajax_glm_members_image_upload',
+ add_action( 'wp_ajax_glm_members_admin_ajax',
array(
$this,
- 'glmMembersImageUpload'
+ 'glmMembersAdminAjax'
)
);
}
/**
- * Image Upload AJAX Target
+ * Admin Ajax Target
+ *
+ * Acccepts all AJAX requests for member db admin.
+ *
+ * Requests are submitted to the WordPress AJAX processor with "action" specified
+ * as "glm_members_admin_ajax". The AJAX call must also specify the target table
+ * the image entry will point to and the target table record ID of the record with
+ * which image will be associated. Only valid tables are accepted according to the
*
- * Acccepts image uploads and routes them to the appropriate
- * model file.
*
* @return void
* @access public
*/
- public function glmMembersImageUpload()
+ public function glmMembersAdminAjax()
{
- // Get the model menu
- if (isset($_REQUEST['glm_menu']) && $_REQUEST['glm_menu'] != '') {
- $a = sanitize_text_field($_REQUEST['glm_menu']);
- if ($a != '') {
- $menuItem = $a;
- } else {
- // No menu provided - terminating
- trigger_error ( 'ERROR: No "glm_menu" string provided in POST array.', E_USER_ERROR);
- }
- } else {
- // Missing glm_menu Item in post array.
- trigger_error ( 'ERROR: No "glm_menu" item in POST array.', E_USER_ERROR);
- }
-
// Get the model action
if (isset($_REQUEST['glm_action']) && $_REQUEST['glm_action'] != '') {
$a = sanitize_text_field($_REQUEST['glm_action']);
if ($a != '') {
- $Action = $a;
+ $glmAction = $a;
} else {
// No menu provided - terminating
trigger_error ( 'ERROR: No "glm_action" string provided in POST array.', E_USER_ERROR);
trigger_error ( 'ERROR: No "glm_action" itme in POST array.', E_USER_ERROR);
}
- // If menu item and action aren't valid, quit now.
- if (! isset($GLOBALS['glmMembersAdminValidActions'][$menuItem]) ||
- ! in_array($Action, $GLOBALS['glmMembersAdminValidActions'][$menuItem])) {
+ // Check for a valid action
+ if (!in_array($glmAction, $GLOBALS['glmMembersAdminValidActions']['ajax'], true)) {
// Menu item/Action not in valid actions array
- trigger_error ( 'ERROR: The specified menu item and action are not valid.', E_USER_ERROR);
+ trigger_error ( 'ERROR: The specified action is not valid.', E_USER_ERROR);
}
// Build model and path and class names
- $modelName = GLM_MEMBERS_PLUGIN_PATH . '/models/admin/' . $menuItem .
- '/' . $Action . '.php';
- $className = 'GlmMembersAdmin_' . $menuItem . '_' . $Action;
+ $modelName = GLM_MEMBERS_PLUGIN_PATH . '/models/admin/ajax/'.$glmAction.'.php';
+ $className = 'GlmMembersAdmin_ajax_'.$glmAction;
// If model file doesn't exist - we have an error
if (!file_exists($modelName)) {
// Verify Menu item and action using array at top of this file
if (! isset($GLOBALS['glmMembersAdminValidActions'][$menuItem]) ||
- ! in_array($action,
- $GLOBALS['glmMembersAdminValidActions'][$menuItem])) {
+ ! in_array($action, $GLOBALS['glmMembersAdminValidActions'][$menuItem])) {
if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) {
$this->addNotice('<b>Error in Admin Controller:</b> Requested Menu Item is invalid!', 'Alert');
$smarty->templateAssign ( 'glmPluginName', GLM_MEMBERS_PLUGIN_NAME );
$smarty->templateAssign ( 'glmPluginMediaURL', GLM_MEMBERS_PLUGIN_MEDIA_URL );
$smarty->templateAssign ( 'thisYear', date ( 'Y' ) );
+ $smarty->templateAssign ( 'ref_type_numb', $this->config['ref_type_numb']);
$smarty->templateAssign ( $this->config['term']);
+ $smarty->templateAssign ( 'term', $this->config['term']);
$smarty->templateAssign ( $this->config['phrase']);
+ $smarty->templateAssign ( 'term', $this->config['phrase']);
$smarty->templateAssign ( 'googleMapsBrowserApiKey', $this->config['googleMapsApiKey']);
// Add data from model to Smarty template
.glm-item-container {
border: 1px #ccc solid;
padding: .4em;
- background: #f8f8f8;
+ background: #fff;
}
/* Admin Tabs */
background-color: #eee;
font-size: .8em;
}
+
+.glm-galleryContainer
+{
+ clear: both;
+ border: 1px #ccc solid;
+ height: 8em;
+ padding: .2em;
+ margin: .4em .1em .4em .1em;
+ background-color: #eee;
+}
+.glm-galleryImages
+{
+
+}
+
+.glm-imageGalleryContainer
+{
+ border: 1px #ddd solid !important;
+ dragable
+}
+.glm-galleryImage
+{
+ float: left;
+ height: 100%;
+ width: 20%;
+ overflow: hidden;
+}
+.glm-galleryImage img
+{
+ position: relative;
+ top: 0px;
+ right: 0px;
+ bottom: 0px;
+ left: 0px;
+ max-height: 100%;
+ max-width: 100%;
+}
+.glm-imageDialog
+{
+ display: none;
+ height: auto;
+ width: auto;
+}
+.glm-galleryImageData
+{
+ float: right;
+ height: 90%;
+ width: 78%;
+ text-align: left;
+ white-space: nowrap;
+}
+.glm-galleryImageData textarea
+{
+ height: 4em;
+ width: 70%;
+ resize: none;
+}
cursor: default;
margin-left: auto;
margin-right: auto;
- width: 75%;
- height: 5em;
+ margin-bottom: 1em;
+ width: 90%;
+ height: 2em;
}
.glm-imageDrop
{
box-shadow: 10px 10px 5px grey;
}
-.glm-imageGalleryImages
-{
-}
-
.glm-statusTable
{
width: 100%;
/* table-layout: fixed; */
line-height: 80%;
}
-.glm-statusImageTD
-{
-/* width: 25%; */
- max-width: 100%;
- overflow: hidden;
- padding: 3px;
- display: table-cell;
- vertical-align: middle;
-}
.glm-statusPrompt
{
width: 10%;
padding: 0px;
text-align: left;
}
+.glm-statusImageTD
+{
+ max-width: 100%;
+ overflow: hidden;
+ padding: 13px;
+ display: table-cell;
+ vertical-align: middle;
+}
.glm-statusImageContainer
{
- display: block;
+ display: block;
width: 100px;
+ height: 100%;
}
-.glm-statusImage
+.glm-statusImageContainer img
{
- height: 5.1em;
- width: auto;
- display: block;
- margin-left: auto;
- margin-right: auto;
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ bottom: 0px;
+ left: 0px;
+ /* Maintain aspect ratio */
+ max-height:100%;
+ max-width: 100%;
}
.glm-progressBarContainer
background-color: blue;
width: 0%;
}
-
/*
- * HTML5 Image Upload Support
+ * Gaslight Media HTML5 Image Upload Support for glm-member-db plugin.
+ *
+ * Author: Chuck Scott <cscott@gaslightmedia.com>
*
* Developed from information in
* http://www.sitepoint.com/html5-file-drag-and-drop/
* http://hayageek.com/drag-and-drop-file-upload-jquery/
+ *
+ * See also the following methods in classes/data/dataImages.php in this plugin.
+ * galleryPositionOrder()
+ * galleryImageDataUpdate()
+ *
*/
-
-/****** NEED TO ADD FILE SIZE TEST AND USER NOTICE ALERT *******/
-
jQuery(document).ready(function($) {
var drop;
var recordID;
- var menuItem;
- var action;
+ var refType;
+ var recordID;
+ var maxFileSize;
+ var allowedTypes;
var files;
-
- // Setup Drag and Drop when Add and
+ var uploadStatusTemplate;
+ var imageDataTemplate;
+ var galleryImages;
+ var newImageAdded = false;
+
+ // Setup Drag and Drop when Add and
if (window.File && window.FileList && window.FileReader) {
// is XHR2 available?
e.preventDefault();
});
- // For each image drop area
+ // For each image drop area on the page
$('.glm-imageDrop').each(function() {
drop = $(this);
- initDrop();
-
- // **** NEED TO DEAL WITH DELAY TILL THE PRIOR DROP AREA HAS BEEN PROCESSED ***
-
+ initDrop();
});
} else {
- $('.glm-noImageDropText').removeClass('glm-imageItemHidden');
+ alert('Your Web browser does not support "Drag & Drop" image uploads using "XHR2".\nThat capability is required to upload images for the image gallery on this page.\nConsider upgrading your browser.');
}
}
- // Setup a single drop area
+ // Setup an image drop area
function initDrop() {
- // Get ID for the record number to which these images belong.
- recordID = drop.attr("data-id");
- menuItem = drop.attr("data-menuItem");
- action = drop.attr("data-action");
+ // Get information from the field on where this image file is going
+ refType = drop.attr("data-refType");
+ recordID = drop.attr("data-recordID");
+ maxFileSize = drop.attr("data-maxFileSizeKB") * 1000;
+ allowedTypes = drop.attr("data-allowedTypes");
+ uploadStatusTemplate = drop.children('.glm-imageUploadStatusTemplate').html();
+ imageDataTemplate = drop.children('.glm-galleryImageDataTemplate').html();
+ galleryImages = drop.parent().parent().children('.glm-galleryImages');
+
// Change drop destination appearance only when dragging over a file.
drop.on('dragenter', function(e){
e.stopPropagation();
}
- /*
- * This function sets up AJAX processing of the list of files.
- * It then fires off the processFile() function to do the first
- * file. When the AJAX call in sendFileToServer() completes,
- * the complete: function will call processFile() again to
- * do the next file, if one exists.
+ /*
+ * This function sets up AJAX processing of the list of files. It then fires
+ * off the processFile() function to do the first file. When the AJAX call
+ * in sendFileToServer() completes, the complete: function will call
+ * processFile() again to do the next file, if one exists.
*/
var thisFile = 0;
var numbFiles = 0;
// Start with the first file
processFile();
-/* var fd = new FormData();
- fd.append('file', file);
-
- var status = new createStatusbar(file, drop);
- statusArea.fadeIn( function() {
- sendFileToServer(fd,status);
- });
-*/
-// statusArea.addClass('glm-imageItemHidden');
-
}
/*
- * Process the current file - AJAX complete: will call back to this
- * function for the next file
+ * Process the current file - AJAX complete: will call back to this function
+ * for the next file
*/
function processFile() {
// Setup field pairs for sending in request
var fd = new FormData();
- fd.append('file', file);
+
+ // Add file upload information
+ fd.append('file', file);
+
+ /*
+ * Add "action" post parameter specifying where WordPress should
+ * route the request. In this case we are routing this AJAX request
+ * to the admin controller glmMembersAdminAjax() method which will
+ * route the request to the proper file in the models/admin/ajax
+ * directory of this plugin.
+ *
+ * see "add_action( 'wp_ajax_glm_members_admin_ajax',..." in admin
+ * controller.
+ */
+ fd.append( 'action', 'glm_members_admin_ajax' );
+
+ // Tell admin controller where to route AJAX call
+ // (models/admin/ajax/imageUpload.php)
+ fd.append('glm_action', 'imageUpload');
+
+ // Tell image upload AJAX processor who the image is for
+ fd.append('glm_refType', refType);
+ fd.append('glm_refDest', recordID);
// Setup status display area
var status = new createStatusbar(file, thisFile, numbFiles);
+
statusArea.fadeIn( function() {
-
- // When status has faded in, Send the files
- sendFileToServer(fd, status, recordID);
+ // Check image size and alert the user if it's too big
+ if (file.size > maxFileSize) {
+
+ alert("This image file is too large to process.\nTo use this image, consider resizing it before uploading.\n\nMaximum image size is " + (maxFileSize/1000) + "KB.");
+ statusArea.fadeOut();
+ processFile();
+
+ // Check the image mime type and alert the user if it's not
+ // permitted
+ } else if (allowedTypes.indexOf(file.type) < 0) {
+
+ alert("The file is not an accepted image type.\nTo use this image, consider resaving it as a differnt image type.\n");
+ statusArea.fadeOut();
+ processFile();
+
+ } else {
+ // When status has faded in, Send the files
+ sendFileToServer(fd, status);
+ }
+
});
thisFile++;
} else {
-
- // done
+
+ // Reset expanded image and sortable events
+ setupExpandedImageEvents();
}
var statusDone = false;
/*
- * We need to redefine these values inside this function
- * so the reader.onload function can see them.
+ * We need to redefine these values inside this function so the
+ * reader.onload function can see them.
*/
var curFile = thisFile + 1;
var lastFile = numbFiles;
statusArea.html('');
// If file is an image
- var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
+// var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
- if (regex.test(file.name.toLowerCase())) {
+// if (regex.test(file.name.toLowerCase())) {
// Create HTML5 file reader and load image
var reader = new FileReader();
reader.onload = function (e) {
- // Add file information to status area
- statusbar =
- '<b><u>Uploading Image {thisFile} of {numbFiles}</u></b>' +
- '<table class="glm-statusTable">' +
- ' <tr><td class="glm-statusImageTD" rowspan="5"><div class="glm-statusImageContainer"><img class="glm-statusImage" src="{fileImage}"></div></td></tr>' +
- ' <tr><td class="glm-statusPrompt">Name: </td><td class="glm-statusValue">{fileName}</td></tr>' +
- ' <tr><td class="glm-statusPrompt">Type: </td><td class="glm-statusValue">{fileType}</td></tr>' +
- ' <tr><td class="glm-statusPrompt">Size: </td><td class="glm-statusValue">{fileSize}</td></tr>' +
- ' <tr><td class="glm-statusPrompt">Progress: </td><td class="glm-statusValue"><div class="glm-progressBarContainer"><div class="glm-progressBar"></div></div></td></tr>' +
- '</table>'
- ;
- statusbar = statusbar.replace('{thisFile}', curFile);
- statusbar = statusbar.replace('{numbFiles}', lastFile);
- statusbar = statusbar.replace('{fileImage}', e.target.result);
- statusbar = statusbar.replace('{fileName}', file.name);
- statusbar = statusbar.replace('{fileType}', file.type);
+ // Using a copy of the supplied template, add file information
+ // to statusbar
+ statusbar = uploadStatusTemplate;
+ statusbar = statusbar.replace('{ thisFile }', curFile);
+ statusbar = statusbar.replace('{ numbFiles }', lastFile);
+ statusbar = statusbar.replace('{ fileImage }', e.target.result);
+ statusbar = statusbar.replace('{ fileName }', file.name);
+ statusbar = statusbar.replace('{ fileType }', file.type);
// Fix up file size string and replace that
var sizeStr="";
{
sizeStr = sizeKB.toFixed(2)+" KB";
}
- statusbar = statusbar.replace('{fileSize}', sizeStr);
+
+ // If a large file, notify user it will take time.
+ if (file.size > 100000 && file.type == 'image/png') {
+ sizeStr += ' -- NOTE: Processing for this image may be slow!';
+ }
+
+ statusbar = statusbar.replace('{ fileSize }', sizeStr);
// Assign the HTML to the status area
statusArea.html(statusbar);
}
reader.readAsDataURL(file);
- } else {
- alert(file.name + " is not a valid image file.");
- statusArea.addClass('glm-imageItemHidden');
- return false;
- }
this.setProgress = function(progress)
{
statusArea.find('.glm-progressBar').css('width', progress + '%');
-
-/*
- var progressBarWidth =progress*this.progressBar.width()/ 100;
- this.progressBar.find('div').animate({ width: progressBarWidth }, 10).html(progress + "% ");
- if(parseInt(progress) >= 100)
- {
- this.abort.hide();
- }
-*/
}
this.setAbort = function(jqxhr)
{
var sb = this.statusbar;
- this.abort.click(function()
+ $('#imageUploadCancel').click(function()
{
jqxhr.abort();
sb.hide();
}
/*
- * Sends file to image plugin via AJAX submission targeting
- * WordPress AJAX handling. An image upload processor has been
- * declared with an add_action() in the admin controller
- * specifying the function containing that processor. We tell
- * WordPress how to route the submission using the "action"
- * post parameter. This matches everything after "wp_ajax_"
- * in the action name.
+ * Sends file to image plugin via AJAX submission targeting WordPress AJAX
+ * handler.
*/
- function sendFileToServer(fd, status, recordID)
+ function sendFileToServer(fd, status)
{
- fd.append( 'action', 'glm_members_image_upload' );
-
var jqXHR=$.ajax({
xhr: function() {
var xhrobj = $.ajaxSettings.xhr();
}
return xhrobj;
},
- url: ajaxurl + '?glm_menu=' + menuItem + '&glm_action=' + action + '&memberInfoID=' + recordID, // WordPress admin AJAX url
+ url: ajaxurl,
type: "POST",
contentType:false,
processData: false,
cache: false,
data: fd,
success: function(data){
-alert(data);
-// status.clearStatus();
-// status.setProgress(100);
-
-// $("#status1").append("File upload Done<br>");
+
+ // Parse returned data
+ fileData = JSON.parse(data);
+
+ // Check for success
+ if (fileData.status) {
+
+ // Add image(s) to gallery display
+ for (f of fileData.files) {
+
+ // Using a copy of the supplied template, add image information
+ imageData = imageDataTemplate;
+ imageData = imageData.replace(/{ id }/g, f.id);
+ imageData = imageData.replace(/\{ filename \}/g, f.newFileName);
+ galleryImages.prepend(imageData);
+
+ // Enable the fields that were just added
+ $("#" + f.id + " input, #" + f.id + " textarea").removeAttr('disabled');
+
+ // Prepend image ID to position order input field
+ $("#galleryPositionOrder").val(f.id + ',' + $("#galleryPositionOrder").val());
+
+ }
+
+ } else {
+ alert('Upload failed');
+ }
+
},
complete: function() {
});
return jqXHR;
-// status.setAbort(jqXHR);
+// status.setAbort(jqXHR);
}
+
+ function setupExpandedImageEvents() {
+
+ // Handle expanded images on hover for image gallery
+ $('.glm-galleryImage').on("mouseenter", function(){
+ id = $(this).attr("data-id");
+ var imgTitle = $("#galleryImage_caption_" + id).val();
+ $('#glm-galleryImageLarger_' + id).dialog({
+ title: imgTitle,
+ dialogClass: "no-close",
+ autoOpen: true,
+ resizable: false,
+ width: 'auto',
+ minWidth: 100,
+ minHeight: 100,
+ create: function() {
+ $(this).dialog('option', 'maxHeight', $(window).height() * .9);
+ $(this).dialog('option', 'maxWidth', $(window).width() * .9);
+ },
+ position: { my: "left+10 top+10", at: "right top", of: $(this), collision: "fit" }
+ });
+ });
+ $('.glm-galleryImage').on("mouseleave", function(){
+ id = $(this).attr("data-id");
+ $('#glm-galleryImageLarger_' + id).dialog("close");
+ });
+ $('.glm-galleryImages').sortable({
+ update: function(event, ui) {
+ var sortedIDs = $(this).sortable('toArray');
+ $('#galleryPositionOrder').val(sortedIDs);
+ }
+ });
+
+ }
+ setupExpandedImageEvents();
});
// Get the desired file name and add a timestamp to it to ensure that it's unique
$fInfo = pathinfo($_FILES[$as.'_new']['name']);
- $newFilename = $prefix.$fInfo['filename'].'_'.time().'.'.$fInfo['extension'];
+ $newFilename = strtolower($fInfo['filename'].'_'.time().'.'.$fInfo['extension']);
// Get image temp file name - Not currently using, but should be using to check for resizing sanity
$size = $newImage->get_size();
*
* @return void
*/
- public function templateAssign($param, $value = null) {
+ public function templateAssign($param, $value = null, $prefix = '') {
// If this is a single assignment
if ($value !== null) {
} elseif (is_array ( $param )) {
while ( list ( $key, $value ) = each ( $param ) ) {
- $this->template->assign ( $key, $value );
+ $this->template->assign ( $prefix.$key, $value );
}
}
}
--- /dev/null
+<?php
+
+/**
+ * Gaslight Media Members Database
+ * Image Upload by AJAX
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package glmMembersDatabase
+ * @author Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version 0.1
+ */
+
+// Load Members data abstract
+require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataImages.php');
+
+/*
+ * This class performs the work of handling images passed to it via
+ * an AJAX call that goes through the WorPress AJAX Handler.
+ *
+ */
+class GlmMembersAdmin_ajax_imageUpload extends GlmDataImages
+{
+
+ /**
+ * WordPress Database Object
+ *
+ * @var $wpdb
+ * @access public
+ */
+ public $wpdb;
+ /**
+ * Plugin Configuration Data
+ *
+ * @var $config
+ * @access public
+ */
+ public $config;
+
+ /*
+ * Constructor
+ *
+ * This contructor sets up this model. At this time that only includes
+ * storing away the WordPress data object.
+ *
+ * @return object Class object
+ *
+ */
+ public function __construct ($wpdb, $config)
+ {
+
+ // Save WordPress Database object
+ $this->wpdb = $wpdb;
+
+ // Save plugin configuration object
+ $this->config = $config;
+
+ // Run constructor for members data class
+ parent::__construct(false, false);
+
+ }
+
+ /*
+ * Perform Model Action
+ *
+ * This method does the work for this model and returns any resulting data
+ *
+ * @return array Status and data array
+ *
+ * 'status'
+ *
+ * True if successfull and false if there was a fatal failure.
+ *
+ * 'menuItemRedirect'
+ *
+ * If not false, provides a menu item the controller should
+ * execute after this one. Normally if this is used, there would also be a
+ * modelRedirect value supplied as well.
+ *
+ * 'modelRedirect'
+ *
+ * If not false, provides an action the controller should execute after
+ * this one.
+ *
+ * 'view'
+ *
+ * A suggested view name that the contoller should use instead of the
+ * default view for this model or false to indicate that the default view
+ * should be used.
+ *
+ * 'data'
+ *
+ * Data that the model is returning for use in merging with the view to
+ * produce output.
+ *
+ */
+ public function modelAction ($actionData = false)
+ {
+
+ $return = array(
+ 'status' => false, // Assume we didn't get files or nothing works
+ 'files' => false, // Provide submitted data along with stored image data
+ 'message' => ''
+ );
+
+ // Check for valid refType - See glmMembersAdminValidActions in Admin Controller
+ if (!isset($_REQUEST['glm_refType']) || !isset($this->config['ref_type_table'][$_REQUEST['glm_refType']])) {
+ $return['message'] = 'Invalid target table specified in AJAX call to imageUpload!';
+ echo json_encode($return);
+ die();
+ }
+ $refType = $_REQUEST['glm_refType'];
+ $refTable = $this->config['ref_type_table'][$_REQUEST['glm_refType']];
+
+ // Check for uploaded files
+ if (!isset($_FILES) || count($_FILES) == 0) {
+ $return['message'] = 'No image file provided!';
+ echo json_encode($return);
+ die();
+ }
+
+ // Check for valid target record ID
+ if (!isset($_REQUEST['glm_refDest']) || ($_REQUEST['glm_refDest']-0) <= 0) {
+ $return['message'] = 'Invalid target ID specified in AJAX call to imageUpload!';
+ echo json_encode($return);
+ die();
+ }
+ $refDest = ($_REQUEST['glm_refDest']-0);
+
+ // Make sure the record actually exists
+ $sql = "SELECT id FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."$refTable WHERE id = $refDest;";
+ $record = $this->wpdb->get_row($sql, ARRAY_A);
+ if ($record['id'] != 1) {
+ $return['message'] = 'Specified target ID does not exist in AJAX call to imageUpload!';
+ echo json_encode($return);
+ die();
+ }
+
+
+ foreach( $_FILES as $file ) {
+
+ // Is there a file of the right type with a temp file that exists
+ if (isset($file['name']) && is_file($file['tmp_name'])) {
+
+ // Get new image using temporary file name
+ $newImage = wp_get_image_editor($file['tmp_name']);
+
+ // If we have a good image
+ if ( ! is_wp_error( $newImage ) ) {
+
+ // Get the desired file name and add a timestamp to it to ensure that it's unique
+ $fInfo = pathinfo($file['name']);
+ $newFilename = strtolower($fInfo['filename'].'_'.time().'.'.$fInfo['extension']);
+
+ // Get image temp file name - Not currently using, but should be using to check for resizing sanity
+ $size = $newImage->get_size();
+
+ // Try to store the image using that file name in the 'original' directory
+ $storedImage = $newImage->save( GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$newFilename );
+
+ // Now resize the images using $sizeArray
+ $sizes = $newImage->multi_resize($this->config['imageSizes']);
+
+ // Finally, move the files to the various size directories and rename them back to the correct name
+ while (list($k, $v) = each($this->config['imageSizes'])) {
+
+ // Check if size directory needs to be made
+ if (!file_exists(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$k)) {
+ mkdir(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$k);
+ }
+
+ // If there's an entry in the $sizes array, it means that the image resized to this size
+ if (isset($sizes[$k])) {
+ // Move resized file to desired direectory
+ rename(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$sizes[$k]['file'], GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$k.'/'.$newFilename);
+ } else {
+ // Image didn't resize to this size, probably because it was smaller than the destination size (silly WP Image Editor class) - so just use the original
+ copy(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$newFilename, GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$k.'/'.$newFilename);
+ }
+
+ }
+
+ // Move the original to original directory
+ if (!file_exists(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/original')) {
+ mkdir(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/original');
+ }
+ rename(GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/'.$newFilename, GLM_MEMBERS_PLUGIN_IMAGES_PATH.'/original/'.$newFilename);
+
+ $file['newFileName'] = $newFilename;
+
+ // Store image name in images table
+ $sql = "
+ INSERT INTO ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images
+ (
+ name,
+ file_name,
+ descr,
+ caption,
+ status,
+ position,
+ ref_type,
+ ref_dest
+ )
+ VALUES
+ (
+ '".$file['name']."',
+ '".$file['newFileName']."',
+ '',
+ '',
+ ".$this->config['status_numb']['Inactive'].",
+ 99,
+ $refType,
+ $refDest
+ );
+ ";
+ $this->wpdb->query($sql);
+ $queryError = $this->wpdb->last_error;
+
+ if ($queryError) {
+ $file['error'] = true;
+ $file['message'] = $queryError."\n".$sql;
+ }
+
+ // Get new ID and data from the new record
+ $file['id'] = $this->wpdb->insert_id;
+ $return['files'][] = $file;
+
+ // Indicate that we actually stored an image
+ $return['status'] = true;
+
+ } else {
+
+ // File was not uploaded or of the wrong type
+ $file['message'] = 'Image file "'.$file['name'].'" was not uploaded or is not a valid image file!';
+ $file['status'] = false;
+
+ }
+
+ }
+
+ }
+
+ // Return stored image data
+ echo json_encode($return);
+ die();
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-
-/**
- * Gaslight Media Members Database
- * Admin Member Info Image Upload by AJAX
- *
- * PHP version 5.5
- *
- * @category glmWordPressPlugin
- * @package glmMembersDatabase
- * @author Chuck Scott <cscott@gaslightmedia.com>
- * @license http://www.gaslightmedia.com Gaslightmedia
- * @version 0.1
- */
-
-// Load Members data abstract
-require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataImages.php');
-
-/*
- * This class performs the work of handling images passed to it via
- * an AJAX call that goes through the WorPress AJAX Handler.
- *
- */
-class GlmMembersAdmin_member_memberImage extends GlmDataImages
-{
-
- /**
- * WordPress Database Object
- *
- * @var $wpdb
- * @access public
- */
- public $wpdb;
- /**
- * Plugin Configuration Data
- *
- * @var $config
- * @access public
- */
- public $config;
-
- /*
- * Constructor
- *
- * This contructor sets up this model. At this time that only includes
- * storing away the WordPress data object.
- *
- * @return object Class object
- *
- */
- public function __construct ($wpdb, $config)
- {
-
- // Save WordPress Database object
- $this->wpdb = $wpdb;
-
- // Save plugin configuration object
- $this->config = $config;
-
- // Run constructor for members data class
- parent::__construct(false, false);
-
- }
-
- /*
- * Perform Model Action
- *
- * This method does the work for this model and returns any resulting data
- *
- * @return array Status and data array
- *
- * 'status'
- *
- * True if successfull and false if there was a fatal failure.
- *
- * 'menuItemRedirect'
- *
- * If not false, provides a menu item the controller should
- * execute after this one. Normally if this is used, there would also be a
- * modelRedirect value supplied as well.
- *
- * 'modelRedirect'
- *
- * If not false, provides an action the controller should execute after
- * this one.
- *
- * 'view'
- *
- * A suggested view name that the contoller should use instead of the
- * default view for this model or false to indicate that the default view
- * should be used.
- *
- * 'data'
- *
- * Data that the model is returning for use in merging with the view to
- * produce output.
- *
- */
- public function modelAction ($actionData = false)
- {
-
- $return = array(
- 'status' => false, // Assume we didn't get files or nothing works
- 'files' => false, // Provide submitted data along with stored image data
- 'message' => false
- );
-
-
- // Check for uploaded files
- if (!isset($_FILES) || count($_FILES) == 0) {
- $return['message'] = 'No image file provided!';
- echo json_encode($return);
- die();
- }
-
- // Include the incoming files data
- $files = $_FILES;
-
- // Check for Member Info record ID
- if (!isset($_REQUEST['memberInfoID']) || trim($_REQUEST['memberInfoID']) == '') {
- $return['message'] = 'No Member Info Record ID provided!';
- echo json_encode($return);
- die();
- }
-echo "memberInfoID = ".$_REQUEST['memberInfoID']."\n\n";
- // Store each file away
-
- // Add stored image to return data
-
- // Return stored image data
- echo json_encode($return);
- die();
- }
-
-
-}
-?>
// Process submission of a member information record update
case 'submit':
+ require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataImages.php');
+ $Images = new GlmDataImages($this->wpdb, $this->config);
+
+ // Update image gallery titles, descriptions, and image positions then return current image gallery
+ $imageGallery = $Images->galleryImageDataUpdate($this->config['ref_type_numb']['MemberInfo'], $memberInfoID, 'galleryPositionOrder');
+ $haveImageGallery = ($imageGallery != false);
+
if ($haveMemberInfo) {
// Update the member Info data
// Also get any image gallery images
require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataImages.php');
$Images = new GlmDataImages($this->wpdb, $this->config);
- $imageGallery = $Images->getGallery($this->config['ref_type_numb']['Member'], $memberInfoID);
-
+ $imageGallery = $Images->getGallery($this->config['ref_type_numb']['MemberInfo'], $memberInfoID);
$haveImageGallery = ($imageGallery != false);
// Otherwise
'haveCategories' => $haveCategories,
'categories' => $categories,
'categoryMemberInfo' => $categoryMemberInfo,
+ 'imageGallery' => $imageGallery,
'noActive' => $noActive,
'time' => time()
);
// 'media_buttons' => true,
// 'quicktags' => false,
'wpautop' => false,
- 'textarea_name' => 'descr', </div>
-
+ 'textarea_name' => 'descr',
'editor_height' => 200, // Height in px, overrides editor_rows
// 'textarea_rows' => 8
));
<tr>
<th>Image Gallery</th>
<td class="glm-item-container glm-imageGalleryContainer">
- <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="300000" />
+ <input type="hidden" id="galleryPositionOrder" name="galleryPositionOrder"
+ value="{foreach $imageGallery as $i name=ig}{if $i.file_name}{$i.id}{if not $smarty.foreach.ig.last},{/if}{/if}{/foreach}" />
<div class="glm-imageDropContainer">
- <div class="glm-imageDrop glm-imageItemHidden" data-refType="" data-recordID="{$memberInfo.fieldData.id}" data-menuItem="member" data-action="memberImage"></div> <!-- Overlay of parent for drag detection -->
+ <!-- All fields with class "glm-imageDrop" are automatically processed by imageUpload.js -->
+ <div class="glm-imageDrop glm-imageItemHidden"
+ data-refType="{$ref_type_numb.MemberInfo}"
+ data-recordID="{$memberInfo.fieldData.id}"
+ data-maxFileSizeKB="2500"
+ data-allowedTypes="image/jpeg,image/png,image/gif,image/x-ms-bmp"
+ >
+ <!-- The contents of this div are read by imageUpload.js to use for display of upload progress. -->
+ <div class="glm-imageUploadStatusTemplate glm-imageItemHidden">
+
+ <!-- Start of upload status pop-up template - Parameters are of the form "[name]" -->
+ <b><u>Uploading Image [thisFile] of [numbFiles]</u></b>
+ <table class="glm-statusTable">
+ <tr><td class="glm-statusImageTD" rowspan="5"><div class="glm-statusImageContainer"><img src="{ fileImage }"></div></td></tr>
+ <tr>
+ <div style="float: right; margin: .2em .2em 0 0;" id="imageUploadCancel" class="button-primary glm-right">Cancel Upload</div>
+ <td class="glm-statusPrompt">Name: </td><td class="glm-statusValue">{ fileName }</td>
+ </tr>
+ <tr><td class="glm-statusPrompt">Type: </td><td class="glm-statusValue">{ fileType }</td></tr>
+ <tr><td class="glm-statusPrompt">Size: </td><td class="glm-statusValue">{ fileSize }</td></tr>
+ <tr><td class="glm-statusPrompt">Progress: </td><td class="glm-statusValue"><div class="glm-progressBarContainer"><div class="glm-progressBar"></div></div></td></tr>
+ </table>
+ <!-- End of template -->
+
+ </div>
+ <!-- The contents of this div are read by imageUpload.js to use as a template for inserting a new image into the gallery area -->
+ <div class="glm-galleryImageDataTemplate glm-imageItemHidden">
+
+ <!--
+ Start of new image template.
+ Parmeters are of the form "{ name }" where the spaces are required to avoid Smarty interpreting the parameters.
+ Note that these input fields are dissabled to avoid the template fields being submitted. The imageUpload.js
+ code enables the fields when it replicates the template for a new image.
+ -->
+ <li id="{ id }" class="glm-galleryContainer">
+ <div class="glm-galleryImageData">
+ <table class="glm-statusTable">
+ <tr>
+ <th>Caption:</th>
+ <td><input id="galleryImage_caption_{ id }" type="text" name="galleryImage_caption[{ id }]" value="" class="glm-form-text-input-medium" disabled></td>
+ <th>Delete:</th>
+ <td><input type="checkbox" name="galleryImage_delete[{ id }]" disabled></td>
+ </tr>
+ <tr>
+ <th>Description:</th>
+ <td><textarea name="galleryImage_descr[{ id }]" disabled></textarea></td>
+ <th colspan="2">New Upload</th>
+ </tr>
+ </table>
+ </div>
+ <div class="glm-galleryImage" data-id="{ id }">
+ <img src="{$glmPluginMediaURL}/images/small/{ filename }">
+ </div>
+ </li>
+ <div id="glm-galleryImageLarger_{ id }" class="glm-imageDialog"><img src="{$glmPluginMediaURL}/images/large/{ filename }"></div>
+ <!-- End of template -->
+
+ </div>
+ </div> <!-- Overlay of parent for drag/drop detection -->
<div class="glm-imageUploadStatus glm-imageItemHidden"></div> <!-- Overlay for Upload Status Bars -->
- <input id="newImage" type="file" name="newImage[]" multiple="multiple" class="glm-form-text-input glm-imageBrowseButton">
<div class="glm-imageDropText glm-imageItemHidden">Drag and drop new images here</div>
<div class="glm-noImageDropText glm-imageItemHidden">HTML5 file drag-and-drop not supported by your browser.<br>Use "Browse" button above to upload an image.</div>
</div>
+ <ul class="glm-galleryImages">
+ <!-- Note that id in li is needed for sorting -->
+ {foreach $imageGallery as $i}
+ {if $i.file_name}
+ <li id="{$i.id}" class="glm-galleryContainer">
+ <div class="glm-galleryImageData">
+ <table class="glm-statusTable">
+ <tr>
+ <th>Caption:</th>
+ <td><input id="galleryImage_caption_{$i.id}" type="text" name="galleryImage_caption[{$i.id}]" value="{$i.caption}" class="glm-form-text-input-medium"></td>
+ <th>Delete:</th>
+ <td><input type="checkbox" name="galleryImage_delete[{$i.id}]"></td>
+ </tr>
+ <tr>
+ <th>Description:</th>
+ <td><textarea name="galleryImage_descr[{$i.id}]">{$i.descr}</textarea></td>
+ <th colspan="2">
+ <input type="hidden" name="galleryImage_position[{$i.id}]" value="{$i.position}">
+ </th>
+ </tr>
+ </table>
+ </div>
+ <div class="glm-galleryImage" data-id="{$i.id}">
+ <img src="{$glmPluginMediaURL}/images/small/{$i.file_name}">
+ </div>
+ <div id="glm-galleryImageLarger_{$i.id}" class="glm-imageDialog"><img src="{$glmPluginMediaURL}/images/large/{$i.file_name}"></div>
+ {/if} </li>
+
+ {/foreach}
+ </div>
</td>
</tr>
</table>
</form>
-<!--
- <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="300000" />
- <div id="newImageButton" class="button-primary glm-right">Add an Image</div>
- <div id="newImageDialog" class="glm-dialog-box" title="Select a new image">
- <table class="glm-admin-table">
- <tr>
- <th class="glm-required">Image:</th>
- <td id="newImageTD">
- <input id="newImage" type="file" name="newImage[]" multiple="multiple" class="glm-form-text-input">
- <div id="imageDrop"><span id="imageDropText">or drop files here</span></div>
- <div id="noImageDrop">HTML5 file drag-and-drop not supported by your browser.<br>Use "Browse" button above to upload an image.</div>
- <div id="newImageRequired"></div>
- </td>
- </tr>
- <tr>
- <th class="glm-required">Image Caption:</th>
- <td id="newImageNameTD">
- <input id="newImageName" type="text" name="newImageName" class="glm-form-text-input">
- <div id="newImageNameRequired"></div>
- </td>
- </tr>
- <tr>
- <th>Description:</th>
- <td>
- <textarea id="editImageDescr" name="descr" class="glm-form-textarea"></textarea>
- </td>
- </tr>
- </table>
- <div id="imageDragMessages">
- <p>Status Messages</p>
- </div>
- <p><span class="glm-required">*</span> Required</p>
- <a id="newImageCancel" class="button-primary glm-right">Cancel</a>
- <input id="newImageSubmit" type="submit" value="Add new image">
- </div>
- -->
-
-
-
<!-- Include scripts for html5-File-Upload -->
<script type="text/javascript">
$('.glm-geocodeAction').change( function() {
glmGeocode();
});
-
-
});
</script>