Merge branch 'develop' into feature/MemberLogin
authorChuck Scott <cscott@gaslightmedia.com>
Mon, 30 Nov 2015 21:14:20 +0000 (16:14 -0500)
committerChuck Scott <cscott@gaslightmedia.com>
Mon, 30 Nov 2015 21:14:20 +0000 (16:14 -0500)
Conflicts:
classes/data/dataMembers.php
glm-member-db.php

35 files changed:
1  2 
activate.php
classes/data/dataAmenities.php
classes/data/dataImages.php
classes/data/dataMemberInfo.php
classes/data/dataMembers.php
classes/glmMemberImportFromConnections.php
config/plugin.ini
controllers/admin.php
controllers/front.php
css/admin.css
glm-member-db.php
js/imageUpload/imageUpload.js
lib/EasyPassword/EasyPassword.php
lib/GlmDataAbstract/DataAbstract.php
lib/GlmDataAbstract/documentation.odt
misc/databaseScripts/create_database_V1.0.43.sql
misc/databaseScripts/update_database_V1.0.43.sql
models/admin/management/addons.php
models/admin/management/import.php
models/admin/management/index.php
models/admin/member/index.php
models/admin/member/memberInfo.php
models/admin/members/list.php
models/front/members/detail.php
models/front/members/list.php
views/admin/dashboardWidget/index.html
views/admin/management/addons.html
views/admin/management/hooks.html
views/admin/management/index.html
views/admin/member/header.html
views/admin/member/index.html
views/admin/member/memberInfo.html
views/admin/members/header.html
views/admin/members/index.html
views/admin/members/list.html

diff --cc activate.php
@@@ -90,8 -90,8 +90,40 @@@ class glmMembersPluginActivate extends 
              // Check for plugin uploads directory
              $this->checkUploadsDir();
  
--            // Add user capabilties
--            $this->addRoleCapability('glm_members_edit',
++
++            // *** TEMPORARY TO DELETE OLD CAPABILOITIES ***
++            $this->deleteRoleCapability('glm_members_edit');
++            $this->deleteRoleCapability('glm_members_info');
++            $this->deleteRoleCapability('glm_members_list');
++
++            /*
++             * Add user capabilties
++             */
++
++            // Access to main menu
++            $this->addRoleCapability('glm_members_main_menu',
++                array(
++                    'administrator' => true,
++                    'author' => false,
++                    'contributor' => false,
++                    'editor' => true,
++                    'subscriber' => false
++                )
++            );
++
++            // Access to Members menu
++            $this->addRoleCapability('glm_members_members',
++                array(
++                    'administrator' => true,
++                    'author' => false,
++                    'contributor' => false,
++                    'editor' => true,
++                    'subscriber' => false
++                )
++            );
++
++            // Access to Member menu
++            $this->addRoleCapability('glm_members_member',
                  array(
                      'administrator' => true,
                      'author' => false,
                      'subscriber' => false
                  )
              );
++
++            // Access to Configure menu
              $this->addRoleCapability('glm_members_configure',
                  array(
                      'administrator' => true,
                      'subscriber' => false
                  )
              );
--            $this->addRoleCapability('glm_members_info',
++
++            // Access to Management menu
++            $this->addRoleCapability('glm_members_management',
                  array(
                      'administrator' => true,
                      'author' => false,
                      'subscriber' => false
                  )
              );
--            $this->addRoleCapability('glm_members_management',
++
++            // Access to Shortcodes menu
++            $this->addRoleCapability('glm_members_shortcodes',
                  array(
                      'administrator' => true,
                      'author' => false,
                  )
              );
  
++            // Display main Dashboard widget
++            $this->addRoleCapability('glm_members_widget',
++                array(
++                    'administrator' => true,
++                    'author' => false,
++                    'contributor' => false,
++                    'editor' => true,
++                    'subscriber' => false
++                )
++            );
++
              // Set current plugin version
              update_option('glmMembersDatabasePluginVersion', GLM_MEMBERS_PLUGIN_VERSION);
  
      }
  
      /*
--     * Add a role capability to all current roles
++     * Add a capability to all current roles
       *
       * @param string $capability Name of capability to add
       * @param array $default Whether capability should be on by default
       * @return void
       * @access private
       */
--    private function addRoleCapability ($capability, $default)
++    private function addRoleCapability($capability, $default)
      {
          // Get list of role objects
          $roleObjects = $GLOBALS['wp_roles']->role_objects;
          // For each role object
          foreach ($roleObjects as $key => $role) {
  
--            // Uncomment to reset capabilities
--            /*
--            if ( isset($role->capabilities[$capability])) {
--                $role->remove_cap($capability);
--            }
--            */
--
              // Check if the role exists in list of editable roles and
              // the capability does not exist
              if (isset($roles[$key]) && ! isset($role->capabilities[$capability])) {
      }
  
  
++    /*
++     * Delete a capability from all current roles
++     *
++     * @param string $capability Name of capability to add
++     *
++     * @return void
++     * @access private
++     */
++    private function deleteRoleCapability($capability)
++    {
++        // Get list of role objects
++        $roleObjects = $GLOBALS['wp_roles']->role_objects;
++
++        // Get list of roles we can edit
++        $roles = get_editable_roles();
++
++        // For each role object
++        foreach ($roleObjects as $key => $role) {
++
++            if ( isset($role->capabilities[$capability])) {
++                $role->remove_cap($capability);
++            }
++
++        }
++
++    }
++
++
  
  }
  
@@@ -194,6 -194,6 +194,7 @@@ class GlmDataAmenities extends GlmDataA
                 AND A.id = R.amenity
            ORDER BY A.name
          ;";
++
          $amenList = $this->wpdb->get_results($sql, ARRAY_A);
  
          return $amenList;
                  VALUES
                      ( $a, $ref_type, $ref_dest )
              ;";
--
              $this->wpdb->query($sql);
  
          }
  
--        return $this->getAmenityRef($ref_type, $ref_dest);
++        $amen = $this->getAmenityRef($ref_type, $ref_dest);
++        return $amen;
  
      }
  
@@@ -134,6 -134,6 +134,20 @@@ class GlmDataImages extends GlmDataAbst
                          'use' => 'a'
                  ),
  
++                // Special Image flag - only one of these
++                'selected' => array (
++                    'field' => 'selected',
++                    'type' => 'checkbox',
++                    'use' => 'gled'
++                ),
++
++                // Featured Image flag
++                'featured' => array (
++                    'field' => 'featured',
++                    'type' => 'checkbox',
++                    'use' => 'gled'
++                ),
++
                  // File Name
                  'file_name' => array(
                          'field' => 'file_name',
                          'use' => 'a'
                  ),
  
++                // Reference Entry ID
++                'ref_dest' => array(
++                        'field' => 'ref_dest',
++                        'type' => 'integer',
++                        'use' => 'gled'
++                ),
++
                  // Reference Destination - Which entry in the table is it associated with
                  'position' => array(
                          'field' => 'position',
                  && is_array($_REQUEST['galleryImage_caption'])
                  && count($_REQUEST['galleryImage_caption']) > 0) {
  
--            // Update text for title and descriptions
++            // Get the ID of the "selected" image - Only one
++            $selected = 0;
++            if (isset($_REQUEST['galleryImage_selected'])) {
++                $selected = ($_REQUEST['galleryImage_selected'] - 0);
++            }
++
++            // Update other data for this image
              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] );
++                $featured = (isset($_REQUEST['galleryImage_featured']) && isset($_REQUEST['galleryImage_featured'][$k]) && $_REQUEST['galleryImage_featured'][$k] == 'on' ? 'true' : 'false');
++
++                // Check if this is the selected image
++                $thisSelected = ($selected == $k ? 'true' : 'false');
  
                  // Update data for this image
--                $sql = "UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images SET caption = '$caption', descr = '$descr' WHERE id = $id;";
++                $sql = "UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX ."images SET caption = '$caption', descr = '$descr', selected = $thisSelected, featured = $featured WHERE id = $id;";
                  $this->wpdb->query($sql);
--
              }
  
              // Check for an image deletion
@@@ -42,296 -42,296 +42,297 @@@ class GlmDataMemberInfo extends GlmData
       */
      public $config;
      /**
 -       * Field definitions
 -       *
 -       * @var $ini
 -       * @access public
 -       */
 -      public $table;
 +     * Field definitions
 +     *
 +     * @var $ini
 +     * @access public
 +     */
 +    public $table;
  
 -      /**
 -       * Field definitions
 -       *
 -       * 'type' is type of field as defined by the application
 -       * text Regular text field
 -       * pointer Pointer to an entry in another table
 -       * 'filters' is the filter name for a particular filter ID in PHP filter
 -       * functions
 -       * See PHP filter_id()
 -       *
 -       * 'use' is when to use the field
 -       * l = List
 -       * g = Get
 -       * n = New
 -       * i = Insert
 -       * e = Edit
 -       * u = Update
 -       * d = Delete
 -       * a = All
 -       *
 -       * @var $ini
 -       * @access public
 -       */
 -      public $fields = false;
 +    /**
 +     * Field definitions
 +     *
 +     * 'type' is type of field as defined by the application
 +     * text Regular text field
 +     * pointer Pointer to an entry in another table
 +     * 'filters' is the filter name for a particular filter ID in PHP filter
 +     * functions
 +     * See PHP filter_id()
 +     *
 +     * 'use' is when to use the field
 +     * l = List
 +     * g = Get
 +     * n = New
 +     * i = Insert
 +     * e = Edit
 +     * u = Update
 +     * d = Delete
 +     * a = All
 +     *
 +     * @var $ini
 +     * @access public
 +     */
 +    public $fields = false;
  
 -      /**
 -       * Constructor
 -       *
 -       * @param object $d
 -       *              database connection
 -       *
 -       * @return void
 -       * @access public
 -       */
 -      function __construct($wpdb, $config)
 -      {
 -
 -          // If this class is not being extended along with existing $wpdb and $config
 -          if (!$this->wpdb) {
 -
 -          // Save WordPress Database object
 -          $this->wpdb = $wpdb;
 -
 -          // Save plugin configuration object
 -          $this->config = $config;
 -
 -          }
 -
 -              /*
 -               * Table Name
 -               */
 -              $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info';
 -
 -              /*
 -               * Table Data Fields
 -               */
 -              $this->fields = array (
 -
 -                              'id' => array (
 -                                              'field' => 'id',
 -                                              'type' => 'integer',
 -                                              'view_only' => true,
 -                                              'use' => 'a'
 -                              ),
 -
 -                      // Member Pointer
 -                      'member' => array (
 -                              'field' => 'member',
 -                              'type' => 'pointer',
 -                            'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members',
 -                            'p_field' => 'name',
 -                                  'p_static' => true,
 -                              'required' => true,
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Member Name (stored by member updates) for sorting
 -                      'member_name' => array(
 -                        'field' => 'member_name',
 -                              'type' => 'text',
 -                              'use' => 'lg'
 -                      ),
 -
 -                      // Member Slug
 -                      'member_slug' => array (
 -                              'field' => 'member',
 -                              'as' => 'member_slug',
 -                              'type' => 'pointer',
 -                            'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members',
 -                            'p_field' => 'member_slug',
 -                                  'p_static' => true,
 -                              'required' => true,
 -                              'use' => 'gle'
 -                      ),
 -
 -                      // Member Pointer index
 -                      'member_pointer' => array (
 -                              'field' => 'member',
 -                              'as' => 'member_pointer',
 -                              'type' => 'integer',
 -                              'required' => true,
 -                              'use' => 'gle'
 -                      ),
 -
 -                      // Reference Name - Not displayed to user
 -                      'reference_name' => array (
 -                                      'field' => 'reference_name',
 -                                      'type' => 'text',
 -                                      'use' => 'a'
 -                      ),
 -
 -                      // Status
 -                              'status' => array (
 -                                              'field' => 'status',
 -                                      'type' => 'list',
 -                                      'list' => $this->config['status'],
 -                                      'required' => true,
 -                                      'default' => $this->config['status_numb']['Pending'],
 -                                      'use' => 'a'
 -                              ),
 -
 -                      // Create Time
 -                      'create_time' => array (
 -                              'field' => 'create_time',
 -                              'type' => 'datetime',
 -                              'use' => 'lgie'
 -                      ),
 -
 -                      // Last Modify Time
 -                      'modify_time' => array (
 -                              'field' => 'modify_time',
 -                              'type' => 'datetime',
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Description
 -                      'descr' => array(
 -                              'field' => 'descr',
 -                              'type' => 'text',
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Short description
 -                      'short_descr' => array (
 -                                      'field' => 'short_descr',
 -                                      'type' => 'text',
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Address Line 1
 -                      'addr1' => array (
 -                                      'field' => 'addr1',
 -                                      'type' => 'text',
 -                                      'use' => 'a'
 -                      ),
 -
 -                      // Address Line 2
 -                      'addr2' => array (
 -                                      'field' => 'addr2',
 -                                      'type' => 'text',
 -                                      'use' => 'a'
 -                      ),
 -
 -                      // City
 -                      'city' => array (
 -                              'field' => 'city',
 -                              'type' => 'pointer',
 -                              'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'cities',
 -                            'p_field' => 'name',
 -                            'p_orderby' => 'name',
 -                                  'p_blank' => true,
 -                              'use' => 'a'
 -                      ),
 -
 -                      // State
 -                              'state' => array (
 -                                              'field' => 'state',
 -                                      'type' => 'list',
 -                                      'list' => $this->config['states'],
 -                                      'default' => 'MI',
 -                                      'use' => 'a'
 -                              ),
 -
 -                      // ZIP / Postal Code
 -                      'zip' => array (
 -                                      'field' => 'zip',
 -                                      'type' => 'text',
 -                                      'use' => 'a'
 -                      ),
 -
 -                      // Country
 -                      'country' => array (
 -                              'field' => 'country',
 -                              'type' => 'list',
 -                              'list' => $this->config['countries'],
 -                              'default' => 'US',
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Latitude
 -                      'lat' => array(
 -                              'field'    => 'lat',
 -                              'type'     => 'float',
 -                              'default'  => $this->config['settings']['maps_default_lat'],
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Longitude
 -                      'lon' => array(
 -                              'field'    => 'lon',
 -                              'type'     => 'float',
 -                              'default'  => $this->config['settings']['maps_default_lon'],
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Region
 -                      'region' => array (
 -                              'field' => 'region',
 -                              'type' => 'pointer',
 -                                  'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'regions',
 -                              'p_field' => 'name',
 -                              'p_orderby' => 'name',
 -                              'p_blank' => true,
 -//                            'force_list' => true,
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Phone
 -                      'phone' => array(
 -                              'field'    => 'phone',
 -                              'type'     => 'phone',
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Toll Free
 -                      'toll_free' => array(
 -                              'field'    => 'toll_free',
 -                              'type'     => 'phone',
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // E-Mail Address
 -                      'email' => array(
 -                              'field'    => 'email',
 -                              'type'     => 'email',
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // URL
 -                      'url' => array(
 -                              'field'    => 'url',
 -                              'type'     => 'text',
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Logo
 -                      'logo' => array(
 -                              'field'    => 'logo',
 -                              'type'     => 'image',
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Credit Cards Accepted - multi-pick
 -                      'cc_type' => array(
 -                              'field'    => 'cc_type',
 -                              'type'     => 'bitmap',
 -                              'bitmap'    => $this->config['credit_card'],
 -                              'default'  => 0, // no cards selected
 -                              'use'      => 'a'
 -                      ),
 -
 -                      // Notes
 -                      'notes' => array (
 -                              'field' => 'notes',
 -                              'type' => 'text',
 -                              'use' => 'a'
 -                      )
 -
 -              );
 -
 -              if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) {
 -                  glmMembersAdmin::addNotice($this->fields, 'DataBlock', 'Table Fields: '.$this->table);
 -              }
 +    /**
 +     * Constructor
 +     *
 +     * @param object $d
 +     *                database connection
 +     *
 +     * @return void
 +     * @access public
 +     */
 +    function __construct($wpdb, $config)
 +    {
 +
 +        // If this class is not being extended along with existing $wpdb and $config
 +        if (!$this->wpdb) {
 +
 +            // Save WordPress Database object
 +            $this->wpdb = $wpdb;
 +
 +            // Save plugin configuration object
 +            $this->config = $config;
 +
 +        }
 +
 +        /*
 +         * Table Name
 +         */
 +        $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info';
 +
 +        /*
 +         * Table Data Fields
 +         */
 +        $this->fields = array (
 +
 +            'id' => array (
 +                'field' => 'id',
 +                'type' => 'integer',
 +                'view_only' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Member Pointer
 +            'member' => array (
 +                'field' => 'member',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members',
 +                    'p_field' => 'name',
 +                    'p_static' => true,
 +                'required' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Member Name (stored by member updates) for sorting
 +            'member_name' => array(
 +                'field' => 'member_name',
 +                'type' => 'text',
 +                'use' => 'lg'
 +            ),
 +
 +            // Member Slug
 +            'member_slug' => array (
 +                'field' => 'member',
 +                'as' => 'member_slug',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members',
 +                    'p_field' => 'member_slug',
 +                    'p_static' => true,
 +                'required' => true,
 +                'use' => 'gle'
 +            ),
 +
 +            // Member Pointer index
 +            'member_pointer' => array (
 +                'field' => 'member',
 +                'as' => 'member_pointer',
 +                'type' => 'integer',
 +                'required' => true,
 +                'use' => 'gle'
 +            ),
 +
 +            // Reference Name - Not displayed to user
 +            'reference_name' => array (
 +                'field' => 'reference_name',
 +                'type' => 'text',
++                'required' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Status
 +            'status' => array (
 +                'field' => 'status',
 +                'type' => 'list',
 +                'list' => $this->config['status'],
 +                'required' => true,
 +                'default' => $this->config['status_numb']['Pending'],
 +                'use' => 'a'
 +            ),
 +
 +            // Create Time
 +            'create_time' => array (
 +                'field' => 'create_time',
 +                'type' => 'datetime',
 +                'use' => 'lgie'
 +            ),
 +
 +            // Last Modify Time
 +            'modify_time' => array (
 +                'field' => 'modify_time',
 +                'type' => 'datetime',
 +                'use' => 'a'
 +            ),
 +
 +            // Description
 +            'descr' => array(
 +                'field' => 'descr',
 +                'type' => 'text',
 +                'use' => 'a'
 +            ),
 +
 +            // Short description
 +            'short_descr' => array (
 +                'field' => 'short_descr',
 +                'type' => 'text',
 +                'use' => 'a'
 +            ),
 +
 +            // Address Line 1
 +            'addr1' => array (
 +                'field' => 'addr1',
 +                'type' => 'text',
 +                'use' => 'a'
 +            ),
 +
 +            // Address Line 2
 +            'addr2' => array (
 +                'field' => 'addr2',
 +                'type' => 'text',
 +                'use' => 'a'
 +            ),
 +
 +            // City
 +            'city' => array (
 +                'field' => 'city',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'cities',
 +                    'p_field' => 'name',
 +                    'p_orderby' => 'name',
 +                    'p_blank' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // State
 +            'state' => array (
 +                'field' => 'state',
 +                'type' => 'list',
 +                'list' => $this->config['states'],
 +                'default' => 'MI',
 +                'use' => 'a'
 +            ),
 +
 +            // ZIP / Postal Code
 +            'zip' => array (
 +                'field' => 'zip',
 +                'type' => 'text',
 +                'use' => 'a'
 +            ),
 +
 +            // Country
 +            'country' => array (
 +                'field' => 'country',
 +                'type' => 'list',
 +                'list' => $this->config['countries'],
 +                'default' => 'US',
 +                'use' => 'a'
 +            ),
 +
 +            // Latitude
 +            'lat' => array(
 +                'field'    => 'lat',
 +                'type'     => 'float',
 +                'default'  => $this->config['settings']['maps_default_lat'],
 +                'use'      => 'a'
 +            ),
 +
 +            // Longitude
 +            'lon' => array(
 +                'field'    => 'lon',
 +                'type'     => 'float',
 +                'default'  => $this->config['settings']['maps_default_lon'],
 +                'use'      => 'a'
 +            ),
 +
 +            // Region
 +            'region' => array (
 +                'field' => 'region',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'regions',
 +                    'p_field' => 'name',
 +                    'p_orderby' => 'name',
 +                    'p_blank' => true,
 +                //  'force_list' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Phone
 +            'phone' => array(
 +                'field'    => 'phone',
 +                'type'     => 'phone',
 +                'use'      => 'a'
 +            ),
 +
 +            // Toll Free
 +            'toll_free' => array(
 +                'field'    => 'toll_free',
 +                'type'     => 'phone',
 +                'use'      => 'a'
 +            ),
 +
 +            // E-Mail Address
 +            'email' => array(
 +                'field'    => 'email',
 +                'type'     => 'email',
 +                'use'      => 'a'
 +            ),
 +
 +            // URL
 +            'url' => array(
 +                'field'    => 'url',
 +                'type'     => 'text',
 +                'use'      => 'a'
 +            ),
 +
 +            // Logo
 +            'logo' => array(
 +                    'field'    => 'logo',
 +                    'type'     => 'image',
 +                    'use'      => 'a'
 +            ),
 +
 +            // Credit Cards Accepted - multi-pick
 +            'cc_type' => array(
 +                    'field'    => 'cc_type',
 +                    'type'     => 'bitmap',
 +                    'bitmap'    => $this->config['credit_card'],
 +                    'default'  => 0, // no cards selected
 +                    'use'      => 'a'
 +            ),
 +
 +            // Notes
 +            'notes' => array (
 +                    'field' => 'notes',
 +                    'type' => 'text',
 +                    'use' => 'a'
 +            )
 +
 +        );
 +
 +        if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) {
 +            glmMembersAdmin::addNotice($this->fields, 'DataBlock', 'Table Fields: '.$this->table);
 +        }
  
        }
  
               WHERE C.id = CMI.category
                 AND CMI.member_info = ".$r['id']."
          ;";
 -          $r['categories'] = $this->wpdb->get_results($sql, ARRAY_A);
 -
 -          // Get Amenity Data for this entry
 -          $sql = "
 -             SELECT A.*
 -               FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "amenities AS A,
 -                    ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "amenity_ref AS R
 -              WHERE R.ref_type = ".$this->config['ref_type_numb']['MemberInfo']."
 -                AND R.ref_dest = ".$r['id']."
 -                AND A.id = R.amenity
 +        $r['categories'] = $this->wpdb->get_results($sql, ARRAY_A);
 +
 +        // Get Amenity Data for this entry
 +        $sql = "
 +           SELECT A.*
 +             FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "amenities AS A,
 +                  ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "amenity_ref AS R
 +            WHERE R.ref_type = ".$this->config['ref_type_numb']['MemberInfo']."
 +              AND R.ref_dest = ".$r['id']."
 +              AND A.id = R.amenity
          ;";
 -          $r['amenities'] = $this->wpdb->get_results($sql, ARRAY_A);
 -          return $r;
 -      }
 +        $r['amenities'] = $this->wpdb->get_results($sql, ARRAY_A);
  
 -      /*
 -       * Get Apha list of first characters in member name
 -       * for those members that have active info.
 -       *
 -       * @param string $where Where clause
 -       *     Note the table refernces M and I.
 -       * @param string $selected Optional selected alpha character
 -       *
 -       * @return object Class object
 -       *
 -       */
 -      public function getAlphaList($where = '', $selected = '')
 -      {
 -
 -          $sql = "
 -             SELECT DISTINCT LEFT(M.name, 1) AS alpha
 -               FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "members M,
 -                    ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "member_info T
 -              WHERE T.status = ".$this->config['status_numb']['Active']."
 -                AND M.id = T.member
 -                    $where
 -              ORDER BY alpha
 -          ;";
 -          $alphaData = $this->wpdb->get_results($sql, ARRAY_A);
 +        return $r;
 +    }
  
 -          // Set selected
 -          foreach ($alphaData as $k=>$v) {
 -              $alphaData[$k]['default'] = ($v['alpha'] == $selected);
 -          }
 +    /*
 +     * Get Apha list of first characters in member name
 +     * for those members that have active info.
 +     *
 +     * @param string $where Where clause
 +     *     Note the table refernces M and I.
 +     * @param string $selected Optional selected alpha character
 +     *
 +     * @return object Class object
 +     *
 +     */
 +    public function getAlphaList($where = '', $selected = '')
 +    {
  
 -          return $alphaData;
 +        $sql = "
 +           SELECT DISTINCT LEFT(M.name, 1) AS alpha
 +             FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "members M,
 +                  ".GLM_MEMBERS_PLUGIN_DB_PREFIX. "member_info T
 +            WHERE T.status = ".$this->config['status_numb']['Active']."
 +              AND M.id = T.member
 +                  $where
 +            ORDER BY alpha
 +        ;";
 +        $alphaData = $this->wpdb->get_results($sql, ARRAY_A);
  
 -      }
 +        // Set selected
 +        foreach ($alphaData as $k=>$v) {
 +            $alphaData[$k]['default'] = ($v['alpha'] == $selected);
 +        }
  
 -      /*
 -       * Get simplified list of member info records.
 -       *
 -       * @param string $where Where clause
 -       *     Note the table refernces M and I.
 -       *
 -       * @return object Class object
 -       *
 -       */
 -      public function getSimpleMemberInfoList($where = '')
 -      {
 -
 -          // Save current list of fields
 -          $f = $this->fields;
 -
 -          // Replace fields list with limited list
 -          $this->fields = array(
 -                      'id' => $f['id'],
 -              'member' => $f['member'],
 -              'member_name' => $f['member_name'],
 -              'member_slug' => $f['member_slug'],
 -              'member_pointer' => $f['member_pointer'],
 -              'reference_name' => $f['reference_name'],
 -                      'status' => $f['status'],
 -              'create_time' => $f['create_time'],
 +        return $alphaData;
 +
 +    }
 +
 +    /*
 +     * Get simplified list of member info records.
 +     *
 +     * @param string $where Where clause
 +     *     Note the table refernces M and I.
 +     *
 +     * @return object Class object
 +     *
 +     */
 +    public function getSimpleMemberInfoList($where = '')
 +    {
 +
 +        // Save current list of fields
 +        $f = $this->fields;
 +
 +        // Replace fields list with limited list
 +        $this->fields = array(
 +            'id' => $f['id'],
 +            'member' => $f['member'],
 +            'member_name' => $f['member_name'],
 +            'member_slug' => $f['member_slug'],
 +            'member_pointer' => $f['member_pointer'],
 +            'reference_name' => $f['reference_name'],
 +            'status' => $f['status'],
 +            'create_time' => $f['create_time'],
              'modify_time' => $f['modify_time']
 -          );
 +        );
  
 -          // Get the simplified list
 -          $list = $this->getList($where);
 +        // Get the simplified list
 +        $list = $this->getList($where);
  
 -          // Restore full fields list
 -          $this->fields = $f;
 +        // Restore full fields list
 +        $this->fields = $f;
  
 -          return $list;
 -      }
 +        return $list;
 +    }
  
  
  }
@@@ -41,195 -41,224 +41,235 @@@ class GlmDataMembers extends GlmDataAbs
       */
      public $config;
      /**
 -       * Field definitions
 -       *
 -       * @var $ini
 -       * @access public
 -       */
 -      public $table;
 -
 -      /**
 -       * Field definitions
 -       *
 -       * 'type' is type of field as defined by the application
 -       * text Regular text field
 -       * pointer Pointer to an entry in another table
 -       * 'filters' is the filter name for a particular filter ID in PHP filter
 -       * functions
 -       * See PHP filter_id()
 -       *
 -       * 'use' is when to use the field
 -       * l = List
 -       * g = Get
 -       * n = New
 -       * i = Insert
 -       * e = Edit
 -       * u = Update
 -       * d = Delete
 -       * a = All
 -       *
 -       * @var $ini
 -       * @access public
 -       */
 -      public $fields = false;
 -
 -      /**
 -       * Constructor
 -       *
 -       * @param object $d
 -       *              database connection
 -       *
 -       * @return void
 -       * @access public
 -       */
 -      function __construct($wpdb, $config)
 -      {
 +     * Field definitions
 +     *
 +     * @var $ini
 +     * @access public
 +     */
 +    public $table;
 +
 +    /**
 +     * Field definitions
 +     *
 +     * 'type' is type of field as defined by the application
 +     * text Regular text field
 +     * pointer Pointer to an entry in another table
 +     * 'filters' is the filter name for a particular filter ID in PHP filter
 +     * functions
 +     * See PHP filter_id()
 +     *
 +     * 'use' is when to use the field
 +     * l = List
 +     * g = Get
 +     * n = New
 +     * i = Insert
 +     * e = Edit
 +     * u = Update
 +     * d = Delete
 +     * a = All
 +     *
 +     * @var $ini
 +     * @access public
 +     */
 +    public $fields = false;
 +
 +    /**
 +     * Constructor
 +     *
 +     * @param object $d
 +     *                database connection
 +     *
 +     * @return void
 +     * @access public
 +     */
 +    function __construct($wpdb, $config)
 +    {
  
          // If this class is not being extended along with existing $wpdb and $config
 -          if (!$this->wpdb) {
 -
 -          // Save WordPress Database object
 -          $this->wpdb = $wpdb;
 -
 -          // Save plugin configuration object
 -          $this->config = $config;
 -          }
 -
 -              /*
 -               * Table Name
 -               */
 -              $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members';
 -
 -              /*
 -               * Table Data Fields
 -               */
 -              $this->fields = array (
 -
 -                              'id' => array (
 -                                              'field' => 'id',
 -                                              'type' => 'integer',
 -                                              'view_only' => true,
 -                                              'use' => 'a'
 -                              ),
 -
 -                              // Status
 -                              'access' => array (
 -                                              'field' => 'access',
 -                                      'type' => 'list',
 -                                      'list' => $this->config['memb_access'],
 -                                          'l_blank' => true,
 -                                      'required' => true,
 -                                      'default' => 30,
 -                                      'force_list' => true,
 -                                      'use' => 'a'
 -                              ),
 -
 -                              // Member Type
 -                              'member_type' => array (
 -                                              'field' => 'member_type',
 -                                              'type' => 'pointer',
 -                                          'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_type',
 -                                          'p_field' => 'name',
 -                                          'p_orderby' => 'name',
 -                                          'p_blank' => true,
 -                                              'required' => true,
 -                                      'force_list' => true,
 -                                              'use' => 'a'
 -                              ),
 -
 -                      // Member Name
 -                              'name' => array (
 -                                              'field' => 'name',
 -                                              'type' => 'text',
 -                                              'required' => true,
 -                                      'unique' => true,
 -                                              'use' => 'a'
 -                              ),
 -
 -                      // Member Name (stored by member updates) for sorting
 -                      'member_slug' => array(
 -                              'field' => 'member_slug',
 -                              'type' => 'text',
 -                              'required' => false,
 -                              'use' => 'gl'
 -                      ),
 -
 -                      // Date created
 -                      'created' => array (
 -                              'field' => 'created',
 -                              'type' => 'date',
 -                              'required' => true,
 -                              'use' => 'a'
 -                      ),
 -
 -                      // Active Version
 -                      'active_id' => array (
 -                              'field' => 'id',
 -                        'as' => 'active_id',
 -                              'type' => 'pointer',
 -                                'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info',
 -                                'p_field' => 'id',
 -                                'p_id' => 'member',
 -                                'p_where' => 'status = '.$this->config['status_numb']['Active'],
 -                              'p_static' => true,
 -                              'use' => 'gl'
 -                      ),
 -
 -                      /*
 -                       *  Has pending information
 -                       *
 -                       *  This is returning the sum of the ID field for all matching entries in the other table
 -                       *  where the ID of the member entry is equal to the 'member' column in the member_info
 -                       *  table and only for those entries where the status column is set to Pending.
 -                       *
 -                       *  If this returns a value of 0, there are no pending informaation records for this member.
 -                       *  If it returns a positive value, there are. The actual positive number returned is
 -                       *  of course not anything useable, only that it's positive.
 -                       *
 -                       */
 -                      'pending' => array (
 -                              'field' => 'id',
 -                        'as' => 'pending',
 -                              'type' => 'pointer',
 -                                'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info',
 -                                'p_field' => 'member',
 -                                'p_id' => 'member',
 -                                'p_where' => 'status = '.$this->config['status_numb']['Pending'],
 -                                'p_sum' => true,
 -                              'use' => 'gl'
 -                      )
 -
 -              );
 -
 -              if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) {
 -                  glmMembersAdmin::addNotice($this->fields, 'DataBlock', 'Table Fields: '.$this->table);
 -              }
 -
 -      }
 -
 -      /*
 -       * Update member slug - should be called after a member record is added or updated
 -       *
 -       * @param integer id ID of member that needs the slug updated
 -       * @access public
 -       */
 -      public function updateSlug($id = false)
 -      {
 -
 -          if ($id == false) {
 -              return false;
 -          }
 -
 -          $m = $this->getEntry($id);
 -
 -          $slug = sanitize_title($m['name']);
 -
 -          // Update the city selected for this memberInfo record
 -          $sql = "
 -            UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX."members
 -                    SET member_slug = '$slug'
 -                    WHERE id = $id
 -                ;";
 -          $this->wpdb->query($sql);
 -
 -          return $slug;
 -
 -      }
 -
 -      /*
 -       * Get a simple members list - Name and ID only
 -       *
 -       * @return array Array of Name and ID for all members
 -       * @access public
 -       */
 -      public function getSimpleMembersList()
 -      {
 -
 -          // Save the current fields array and make a copy
 -          $fSave = $this->fields;
 -          $f = $fSave;
 -
 -          // Remove what we don't want form the copy and get the list
 -          unset($f['access'], $f['member_type'], $f['created']);
 -          $this->fields = $f;
 -          $memberList = $this->getList();
 -
 -          // Restore the fields list
 -          $this->fields = $fSave;
 -
 -          return $memberList;
 -      }
 +        if (!$this->wpdb) {
 +
 +            // Save WordPress Database object
 +            $this->wpdb = $wpdb;
 +
 +            // Save plugin configuration object
 +            $this->config = $config;
 +        }
 +
 +        /*
 +         * Table Name
 +         */
 +        $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'members';
 +
 +        /*
 +         * Table Data Fields
 +         */
 +        $this->fields = array (
 +
 +            'id' => array (
 +                'field' => 'id',
 +                'type' => 'integer',
 +                'view_only' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Status
 +            'access' => array (
 +                'field' => 'access',
 +                'type' => 'list',
-                 'list' => $this->config['memb_access'],
++                'list' => $this->config['access'],
 +                    'l_blank' => true,
 +                'required' => true,
 +                'default' => 30,
 +                'force_list' => true,
 +                'use' => 'a'
 +            ),
 +
++            // Status - Display only short version
++            'access_short' => array (
++                'field' => 'access',
++                'as' => 'access_short',
++                'type' => 'list',
++                'list' => $this->config['access_short'],
++                    'l_blank' => true,
++                'required' => true,
++                'default' => 30,
++                'force_list' => true,
++                'use' => 'lged'
++            ),
++
 +            // Member Type
 +            'member_type' => array (
 +                'field' => 'member_type',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_type',
 +                    'p_field' => 'name',
 +                    'p_orderby' => 'name',
-                     'p_blank' => true,
 +                'required' => true,
 +                'force_list' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Member Name
 +            'name' => array (
 +                'field' => 'name',
 +                'type' => 'text',
 +                'required' => true,
 +                'unique' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Member Name (stored by member updates) for sorting
 +            'member_slug' => array(
 +                'field' => 'member_slug',
 +                'type' => 'text',
-                 'required' => true,
-                 'use' => 'a'
++                'use' => 'gl'
 +            ),
 +
 +            // Date created
 +            'created' => array (
 +                'field' => 'created',
 +                'type' => 'date',
 +                'required' => true,
 +                'use' => 'a'
 +            ),
 +
 +            // Active Version
 +            'active_id' => array (
 +                'field' => 'id',
 +                'as' => 'active_id',
 +                'type' => 'pointer',
 +                    'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info',
 +                    'p_field' => 'id',
 +                    'p_id' => 'member',
 +                    'p_where' => 'status = '.$this->config['status_numb']['Active'],
 +                'p_static' => true,
 +                'use' => 'gl'
 +            ),
 +
 +            /*
 +             *  Has pending information
 +             *
 +             *  This is returning the sum of the ID field for all matching entries in the other table
 +             *  where the ID of the member entry is equal to the 'member' column in the member_info
 +             *  table and only for those entries where the status column is set to Pending.
 +             *
 +             *  If this returns a value of 0, there are no pending informaation records for this member.
 +             *  If it returns a positive value, there are. The actual positive number returned is
 +             *  of course not anything useable, only that it's positive.
 +             *
 +             */
 +            'pending' => array (
 +                    'field' => 'id',
 +                    'as' => 'pending',
 +                    'type' => 'pointer',
 +                      'p_table' => GLM_MEMBERS_PLUGIN_DB_PREFIX . 'member_info',
 +                      'p_field' => 'member',
 +                      'p_id' => 'member',
 +                      'p_where' => 'status = '.$this->config['status_numb']['Pending'],
 +                      'p_sum' => true,
 +                    'use' => 'gl'
 +            )
 +
 +        );
 +
 +        if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) {
 +            glmMembersAdmin::addNotice($this->fields, 'DataBlock', 'Table Fields: '.$this->table);
 +        }
 +
 +    }
 +
++    /*
++     * Update member slug - should be called after a member record is added or updated
++     *
++     * @param integer id ID of member that needs the slug updated
++     * @access public
++     */
++    public function updateSlug($id = false)
++    {
++
++        if ($id == false) {
++            return false;
++        }
++
++        $m = $this->getEntry($id);
++
++        $slug = sanitize_title($m['name']);
++
++        // Update the city selected for this memberInfo record
++        $sql = "
++         UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX."members
++                 SET member_slug = '$slug'
++                 WHERE id = $id
++             ;";
++        $this->wpdb->query($sql);
++
++        return $slug;
++
++}
++
 +    /*
 +     * Get a simple members list - Name and ID only
 +     *
 +     * @return array Array of Name and ID for all members
 +     * @access public
 +     */
 +    public function getSimpleMembersList()
 +    {
 +
 +        // Save the current fields array and make a copy
 +        $fSave = $this->fields;
 +        $f = $fSave;
 +
 +        // Remove what we don't want form the copy and get the list
 +        unset($f['access'], $f['member_type'], $f['created']);
 +        $this->fields = $f;
 +        $memberList = $this->getList();
 +
 +        // Restore the fields list
 +        $this->fields = $fSave;
 +
 +        return $memberList;
 +    }
  
  }
  
@@@ -339,7 -339,7 +339,7 @@@ class GlmMemberImportFromConnection
                          )
                      VALUES
                          (
--                        ".$this->config['memb_access_numb']['Moderated'].",
++                        ".$this->config['access_numb']['Moderated'].",
                          $membTypeID,
                          '".$m['ts']."',
                          '".addslashes($m['organization'])."'
@@@ -53,17 -55,17 +53,23 @@@ status_numb['Archived'] = 9
  ;
  ; Member Access Levels
  ;
--memb_access[30] = 'Display, Member Updates Moderated'
--memb_access[40] = 'Display, Member Updates Not Moderated'
--memb_access[20] = 'Display, No Memb Access'
--memb_access[10] = 'Not Displayed, No Member Access'
--memb_access[90] = 'Not Displayed, Archived'
--
--memb_access_numb['NotDisplayed'] = 10
--memb_access_numb['NoAccess'] = 20
--memb_access_numb['Moderated'] = 30
--memb_access_numb['Full'] = 40
--memb_access_numb['Archived'] = 90
++access[30] = 'Display, Updates Moderated'
++access[40] = 'Display, Updates Not Moderated'
++access[20] = 'Display, No Access'
++access[10] = 'Not Displayed, No Access'
++access[90] = 'Not Displayed, Archived'
++
++access_short[30] = 'Moderated'
++access_short[40] = 'Not-Moderated'
++access_short[20] = 'Display'
++access_short[10] = 'None'
++access_short[90] = 'Archived'
++
++access_numb['NotDisplayed'] = 10
++access_numb['NoAccess'] = 20
++access_numb['Moderated'] = 30
++access_numb['Full'] = 40
++access_numb['Archived'] = 90
  
  ;
  ; Entity Reference Type
@@@ -324,71 -376,68 +324,89 @@@ class glmMembersAdmin extends GlmPlugin
      {
  
          // Add a new main menu item for management and display of Members
-         add_menu_page(
-             'Members',
-             'Member DB',
-             'glm_members_edit',
-             'glm-members-admin-menu-members',
-             function() {$this->controller('members');},
-             false,
-             '91.123'
-         );
 -        add_menu_page('Members', 'Member DB', 'glm_members_edit',
++        if (apply_filters('glm_members_menu_members', true)) {
++
++            $mainMenuSlug = 'glm-members-admin-menu-members';
++
++            add_menu_page(
++                'Members',
++                'Members',
++                'glm_members_main_menu',
+                 'glm-members-admin-menu-members',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuMembers'
 -                ), false, '91.123');
++                function() {$this->controller('members');},
++                false,
++                '91.123'
++            );
  
-         // Add a submenu for Member List
-         add_submenu_page(
-             'glm-members-admin-menu-members',
-             'Member List',
-             '&nbsp;&nbsp;Member List',
-             'glm_members_edit',
-             'glm-members-admin-menu-members-list',
-             function() {$this->controller('members', 'list');}
-         );
 -        /*
 -         *  Add a submenu for the "Members" section
 -         *  Note that this uses the main menu item's slug for both the parent and menu slug
 -         *  to create a sub-menu with a title different from the main menu title
 -         */
++            // Add a submenu for the "Member" section
++            if (apply_filters('glm_members_menu_member', true)) {
++                add_submenu_page(
++                    $mainMenuSlug,
++                    'Member Dashboard',
++                    'Member',
++                    'glm_members_member',
++                    'glm-members-admin-menu-member',
++                    function() {$this->controller('member');}
++                );
++            }
  
-         // Add a submenu for the "Member" section
-         add_submenu_page(
-             'glm-members-admin-menu-members',
-             'Member Information',
-             'Add Member',
-             'glm_members_edit',
-             'glm-members-admin-menu-member',
-             function() {$this->controller('member');}
-         );
 -        add_submenu_page('glm-members-admin-menu-members', 'Members',
 -                'Members', 'glm_members_edit', 'glm-members-admin-menu-members',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuMembers'
 -                ));
++        } else {
 -        // Add a submenu for Member List
 -        add_submenu_page('glm-members-admin-menu-members', 'Member List',
 -                '&nbsp;&nbsp;Member List', 'glm_members_edit', 'glm-members-admin-menu-members-list',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuMembersList'
 -                ));
++            $mainMenuSlug = 'glm-members-admin-menu-member';
 -        // Add a submenu for the "Member" section
 -        add_submenu_page('glm-members-admin-menu-members', 'Member Information',
 -                'Add Member', 'glm_members_edit', 'glm-members-admin-menu-member',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuMember'
 -                ));
++            add_menu_page(
++                'Member',
++                'Member',
++                'glm_members_main_menu',
++                'glm-members-admin-menu-member',
++                function() {$this->controller('member');},
++                false,
++                '91.123'
++            );
++
++        }
  
          // Add a submenu for the "Configure" section
-         add_submenu_page(
-             'glm-members-admin-menu-members',
-             'Configure Members Database',
-             'Configure',
-             'glm_members_configure',
-             'glm-members-admin-menu-configure',
-             function() {$this->controller('configure');}
-         );
 -        add_submenu_page('glm-members-admin-menu-members',
 -                'Configure Members Database', 'Configure',
 -                'glm_members_configure', 'glm-members-admin-menu-configure',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuConfigure'
 -                ));
++        if (apply_filters('glm_members_menu_configure', true)) {
++            add_submenu_page(
++                'glm-members-admin-menu-members',
++                'Configure Members Database',
++                'Configure',
++                'glm_members_configure',
++                'glm-members-admin-menu-configure',
++                function() {$this->controller('configure');}
++            );
++        }
  
          // Add a submenu for the "Management" section
-         add_submenu_page(
-             'glm-members-admin-menu-members',
-             'Member DB Management',
-             'Management',
-             'glm_members_management',
-             'glm-members-admin-menu-management',
-             function() {$this->controller('management');}
-         );
 -        add_submenu_page('glm-members-admin-menu-members',
 -                'Member DB Management', 'Management',
 -                'glm_members_management', 'glm-members-admin-menu-management',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuManagement'
 -                ));
++        if (apply_filters('glm_members_menu_meanagement', true)) {
++            add_submenu_page(
++                'glm-members-admin-menu-members',
++                'Member DB Management',
++                'Management',
++                'glm_members_management',
++                'glm-members-admin-menu-management',
++                function() {$this->controller('management');}
++            );
++        }
  
          // Add a submenu for the "Shortcode Reference" section
-         add_submenu_page(
-             'glm-members-admin-menu-members',
-             'Shortcode Reference',
-             'Shortcodes',
-             'glm_members_info',
-             'glm-members-admin-menu-shortcodes',
-             function() {$this->controller('shortcodes');}
-         );
 -        add_submenu_page('glm-members-admin-menu-members',
 -                'Shortcode Reference', 'Shortcodes',
 -                'glm_members_info', 'glm-members-admin-menu-shortcodes',
 -                array(
 -                        $this,
 -                        'glmMembersAdminMenuShortcodes'
 -                ));
++        if (apply_filters('glm_members_menu_shortcodes', true)) {
++            add_submenu_page(
++                'glm-members-admin-menu-members',
++                'Shortcode Reference',
++                'Shortcodes',
++                'glm_members_shortcodes',
++                'glm-members-admin-menu-shortcodes',
++                function() {$this->controller('shortcodes');}
++            );
++        }
 +
 +        // For each add-on, read in their menu additions
 +        foreach ($this->config['addOns'] as $a) {
 +            require_once(GLM_MEMBERS_WORDPRESS_PLUGIN_PATH.$a['slug'].'/setup/adminMenus.php');
 +            require_once(GLM_MEMBERS_WORDPRESS_PLUGIN_PATH.$a['slug'].'/setup/adminTabs.php');
 +        }
  
      }
  
      public function glmMembersAdminDashboardWidget ()
      {
  
--        if ( current_user_can( 'glm_members_info' ) ) {
++        if ( current_user_can( 'glm_members_widget' ) ) {
  
              wp_add_dashboard_widget(
 -                    'glm_members_admin_dashboard_widget',
 -                    'Member DB Summary',
 -                    array(
 -                            $this,
 -                            'glmMembersAdminDashboardContent'
 -                    )
 +                'glm_members_admin_dashboard_widget',
 +                'Member DB Summary',
 +                function() {$this->controller('dashboardWidget'); }
              );
  
              // Set widget default position to right column
@@@ -311,7 -328,7 +311,8 @@@ class glmMembersFront extends GlmPlugin
              $modelRedirect = false;
  
              // Verify that we have the requested menu item in the valid actions
--            if (! isset($GLOBALS['glmMembersFrontValidActions'][$menuItem])) {
++
++            if (! isset($GLOBALS['glmMembersValidActions']['frontActions'][$menuItem])) {
                  $modelRedirect = true;
                  $menuItem = 'error';
                  $action = 'index';
              }
  
              // Verify Menu item and action using array at top of this file
--            if (! isset($GLOBALS['glmMembersFrontValidActions'][$menuItem]) ||
--                     ! in_array($action,
--                            $GLOBALS['glmMembersFrontValidActions'][$menuItem])) {
++            if (! isset($GLOBALS['glmMembersValidActions']['frontActions']) ||
++                     ! isset($action,
++                            $GLOBALS['glmMembersValidActions']['frontActions'][$menuItem])) {
                  $menuItem = 'error';
                  $action = 'badAction';
              }
diff --cc css/admin.css
      white-space: nowrap;
      padding-right: 1em;
      padding-bottom: .4em;
--    width: 10px;        /* used to keep header fields on a line with td's to as narrow as they can be without breaking the text */
++    width: 1%;      /* used to keep header fields on a line with td's to as narrow as they can be without breaking the text */ 
  }
  .glm-admin-table td {
      text-align: left;
      vertical-align: top;
--    padding-bottom: .4em;
++    padding-bottom: .2em;
  }
  .glm-admin-table thead th{
      font-size: 15px;
  .glm-admin-table-active {
      background: #99FFFF;
  }
++.glm-admin-table-medium-text {
++    font-size: 0.9em;
++    margin: 0px;
++}
++.glm-admin-table-small-text {
++    font-size: 0.8em;
++    margin: 0px;
++}
  .glm-admin-image-edit-table {
      border: 2px #ddd solid;
  }
  .glm-admin-image-edit-table td {
      padding: 5px;
  }
++td.glm-shrink {
++  white-space: nowrap;
++  width: 1px;
++}
++td.glm-nowrap {
++  white-space: nowrap;
++}
  
 +/* Misc Admin */
 +.glm-code {
 +    font-size: .8em;
 +    font-family: "Courier New", Courier, monospace;
 +    white-space: pre;
 +}
++.glm-li {
++    list-style-type: circle;
++    padding-left: 1em;
++}
  
  /* Overlay dialog box */
  .glm-dialog-box {
  {
      float: left;
      height: 100%;
--    width: 20%;
++/*    width: 20%;*/
      overflow: hidden;
  }
  .glm-galleryImage img
@@@ -3,7 -3,7 +3,7 @@@
   * Plugin Name: GLM Members Database
   * Plugin URI: http://www.gaslightmedia.com/
   * Description: Gaslight Media Members Database.
-  * Version: 1.0.41
 - * Version: 1.0.42
++ * Version: 1.0.43
   * Author: Chuck Scott
   * Author URI: http://www.gaslightmedia.com/
   * License: GPL2
@@@ -19,7 -19,7 +19,7 @@@
   * @package glmMembersDatabase
   * @author Chuck Scott <cscott@gaslightmedia.com>
   * @license http://www.gaslightmedia.com Gaslightmedia
-  * @version 1.0.41
 - * @version 1.0.42
++ * @version 1.0.43
   */
  
  /*
   *  version when there's a change in the database!! Use the
   *  version nunmber of that release for the DB version.
   */
 -define('GLM_MEMBERS_PLUGIN_VERSION', '1.0.42');
 -define('GLM_MEMBERS_PLUGIN_DB_VERSION', '1.0.30');
++
 +define('GLM_MEMBERS_PLUGIN_VERSION', '1.0.43');
 +define('GLM_MEMBERS_PLUGIN_DB_VERSION', '1.0.43');
 +
 +/**
 + * Array of valid menu items and actions.
 + *
 + * The higher level elements are valid menu items. These correlate to
 + * actual menu or sub menu items that are hooks back to this controller
 + * class.
 + *
 + * The lower level items below each menu item are actions that may be specified
 + * by a "glmMembersAction" form field.
 + *
 + * The string after the action is the slug of the plugin where the model/view
 + * is to perform that action.
 + *
 + * This array is extended to include valid menus and actions from any add-on
 + * plugins.
 + */
 +$GLOBALS['glmMembersValidActions'] = array(
 +    'adminActions' => array(
 +        'ajax' => array(
 +                'imageUpload' => 'glm-member-db'
 +        ),
 +        'dashboardWidget' => array(
 +                'index' => 'glm-member-db'
 +        ),
 +        'members' => array(
 +                'index' => 'glm-member-db',            // member list
 +                'list' => 'glm-member-db',
 +                'reports' => 'glm-member-db',
 +                'other' => 'glm-member-db'
 +        ),
 +        'member' => array(
 +                'index' => 'glm-member-db',            // Member Dashboard
 +                'memberInfo' => 'glm-member-db',
 +                'locations' => 'glm-member-db',
 +                'facilities' => 'glm-member-db',
 +                'activities' => 'glm-member-db',
 +                'accommodations' => 'glm-member-db'
 +        )
 +        ,
 +        'configure' => array(
 +                'index' => 'glm-member-db',            // Member Types
 +                'categories' => 'glm-member-db',
 +                'cities' => 'glm-member-db',
 +                'regions' => 'glm-member-db',
 +                'accommodationTypes' => 'glm-member-db',
 +                'amenities' => 'glm-member-db'
 +        ),
 +        'management' => array(
 +                'index' => 'glm-member-db',            // General Options
 +                'terms' => 'glm-member-db',
 +                'development' => 'glm-member-db',
 +                'import' => 'glm-member-db',
 +                'addons' => 'glm-member-db',
 +                'hooks' => 'glm-member-db'
 +        ),
 +        'shortcodes' => array(
 +                'index' => 'glm-member-db'
 +        ),
 +        'error' => array(
 +                'index' => 'glm-member-db',
 +                'badAction' => 'glm-member-db'
 +        )
 +    ),
 +    'frontActions' => array(
 +        'members' => array(
 +            'list' => 'glm-member-db',
 +            'detail' => 'glm-member-db'
 +        ),
 +        'error' => array(
 +            'index' => 'glm-member-db',
 +            'badAction' => 'glm-member-db'
 +        )
 +    )
 +);
  
  /*
   * Copyright 2014 Charles Scott (email : cscott@gaslightmedia.com)
@@@ -345,6 -237,6 +346,32 @@@ register_deactivation_hook(__FILE__, 'g
  // Load data abstract
  require_once(GLM_MEMBERS_PLUGIN_LIB_PATH.'/GlmDataAbstract/DataAbstract.php');
  
++/*
++ *  Hook through which an add-on may supply additional logged in user information and
++ *  have that data stored in the config array. Typically it would be the
++ *  glm-members-db-contacts add-on supplying the information.
++ *
++ *  This hook provides default data with the current WordPress user 'data' object
++ *  as a 'wpUser' sub-array if a WordPress user is logged in. If not 'wpUser' will
++ *  be false. The supplied data is the basic information on the WordPress user
++ *  provided by the 'data' object from wp_get_current_user().
++ *
++ *  To permit more than one routine to access this filter and therefore to supply
++ *  additional information on the logged in user, code may merge it's own data or may
++ *  add another sub-array containing user information specific to an add-on (i.e.
++ *  contacts add-on might supply a 'contactUser' sub-array).
++ *
++ */
++if (function_exists('is_user_logged_in')) {
++    $config['loggedInUser'] = array(
++        'wpUser' => false
++    );
++    if (is_user_logged_in()) {
++        $config['loggedInUser']['wpUser'] = (array) wp_get_current_user()->data;
++    }
++    $config['loggedInUser'] = apply_filters('glm_members_current_logged_in_user', $config['loggedInUser']);
++}
++
  /*
   *
   * Determine which controller to load
  
  jQuery(document).ready(function($) {
  
 -      
 -      var drop;
 -      var recordID;
 -      var refType;
 -      var recordID;
 -      var maxFileSize;
 -      var allowedTypes;
 -      var files;
 -      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?
 -              var xhr = new XMLHttpRequest();
 -              if (xhr.upload) {
 -
 -                      // Change from Drag/Drop not supported to drop here text
 -                      $('.glm-imageBrowseButton').addClass('glm-imageItemHidden');
 -                      $('.glm-imageDropText').removeClass('glm-imageItemHidden');
 -                      $('.glm-imageDrop').removeClass('glm-imageItemHidden');
 -
 -                      // Prevent dropping on the document
 -                      $(document).on('dragenter', function (e) {
 -                          e.stopPropagation();
 -                          e.preventDefault();
 -                      });
 -                      $(document).on('dragover', function (e) {
 -                        e.stopPropagation();
 -                        e.preventDefault();
 -                      });
 -                      $(document).on('drop', function (e) {
 -                          e.preventDefault();
 -                      });
 -                      
 -                      // For each image drop area on the page
 -                      $('.glm-imageDrop').each(function() {
 -                              drop = $(this);
 -                              initDrop();                             
 -                      });
 -
 -              } else {
 -                      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 an image drop area
 -      function initDrop() {
 -
 -              // 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();
 -                      e.preventDefault();
 -                      drop.parent().addClass('glm-imageDropDragOver');
 -              });
 -              drop.on('dragover', function(e){
 -                      e.stopPropagation();
 -                      e.preventDefault();
 -              });
 -              drop.on('dragleave', function(e){
 -                      e.stopPropagation();
 -                      e.preventDefault();
 -                      drop.parent().removeClass('glm-imageDropDragOver');
 -              });
 -              
 -              // File drop action
 -              $('.glm-imageDrop').on('drop', function (e) { 
 -                      e.preventDefault();
 -                      files = e.originalEvent.dataTransfer.files;
 -                      handleFileDrop();
 -                      drop.parent().removeClass('glm-imageDropDragOver');
 -              });
 -
 -      }
 -      
 -      /*
 -       * 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;
 -
 -      function handleFileDrop() {
 -              
 -              // Reset file pointer and set number of last file
 -              thisFile = 0;
 -              numbFiles = files.length;
 -
 -              // Start with the first file
 -              processFile();
 -              
 -      }
 -      
 -      /*
 -       * Process the current file - AJAX complete: will call back to this function
 -       * for the next file
 -       */ 
 -      function processFile() {
 -
 -              // If we still have files to process
 -              if (thisFile < numbFiles) {
 -                      
 -                      file = files[thisFile];
 -                      
 -                      // Setup field pairs for sending in request
 -                      var fd = new FormData();
 -                      
 -                      // 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() {
 -              
 -                      // 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 {
 -
 -                      // Reset expanded image and sortable events
 -                      setupExpandedImageEvents();
 -                      
 -              }
 -
 -      }       
 -      
 -      function createStatusbar(file, thisFile, numbFiles)
 -      {
 -              var statusDone = false;
 -              
 -              /*
 -               * We need to redefine these values inside this function so the
 -               * reader.onload function can see them.
 -               */
 -              var curFile = thisFile + 1;
 -              var lastFile = numbFiles;
 -              
 -              // Get status area for this drop area
 -              statusArea = drop.siblings('.glm-imageUploadStatus');
 -
 -              // Make status area visible (overlay) and clear contents
 -              statusArea.html('');
--
 -              // If file is an image
 +    var drop;
 +    var recordID;
 +    var refType;
 +    var recordID;
 +    var maxFileSize;
 +    var allowedTypes;
 +    var files;
 +    var uploadStatusTemplate;
 +    var imageDataTemplate;
 +    var galleryImages;
 +    var newImageAdded = false;
++    var enableDragable = true;
 +
 +    // Setup Drag and Drop when Add and
 +    if (window.File && window.FileList && window.FileReader) {
 +
 +        // is XHR2 available?
 +        var xhr = new XMLHttpRequest();
 +        if (xhr.upload) {
 +
 +            // Change from Drag/Drop not supported to drop here text
 +            $('.glm-imageBrowseButton').addClass('glm-imageItemHidden');
 +            $('.glm-imageDropText').removeClass('glm-imageItemHidden');
 +            $('.glm-imageDrop').removeClass('glm-imageItemHidden');
 +
 +            // Prevent dropping on the document
 +            $(document).on('dragenter', function (e) {
 +                e.stopPropagation();
 +                e.preventDefault();
 +            });
 +            $(document).on('dragover', function (e) {
 +              e.stopPropagation();
 +              e.preventDefault();
 +            });
 +            $(document).on('drop', function (e) {
 +                e.preventDefault();
 +            });
 +
 +            // For each image drop area on the page
 +            $('.glm-imageDrop').each(function() {
 +                drop = $(this);
 +                initDrop();
 +            });
 +
 +        } else {
 +            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 an image drop area
 +    function initDrop() {
 +
 +        // 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();
 +              e.preventDefault();
 +              drop.parent().addClass('glm-imageDropDragOver');
 +        });
 +        drop.on('dragover', function(e){
 +              e.stopPropagation();
 +              e.preventDefault();
 +        });
 +        drop.on('dragleave', function(e){
 +              e.stopPropagation();
 +              e.preventDefault();
 +              drop.parent().removeClass('glm-imageDropDragOver');
 +        });
 +
 +        // File drop action
 +        $('.glm-imageDrop').on('drop', function (e) {
 +            e.preventDefault();
 +            files = e.originalEvent.dataTransfer.files;
 +            handleFileDrop();
 +            drop.parent().removeClass('glm-imageDropDragOver');
 +        });
 +
 +    }
 +
 +    /*
 +     * 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;
 +
 +    function handleFileDrop() {
 +
 +      // Reset file pointer and set number of last file
 +      thisFile = 0;
 +      numbFiles = files.length;
 +
 +      // Start with the first file
 +      processFile();
 +
 +    }
 +
 +    /*
 +     * Process the current file - AJAX complete: will call back to this function
 +     * for the next file
 +     */
 +    function processFile() {
 +
 +        // If we still have files to process
 +        if (thisFile < numbFiles) {
 +
 +            file = files[thisFile];
 +
 +            // Setup field pairs for sending in request
 +            var fd = new FormData();
 +
 +            // 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() {
 +
 +                // 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 {
 +
 +            // Reset expanded image and sortable events
 +            setupExpandedImageEvents();
 +
 +        }
 +
 +    }
 +
 +    function createStatusbar(file, thisFile, numbFiles)
 +    {
 +        var statusDone = false;
 +
 +        /*
 +         * We need to redefine these values inside this function so the
 +         * reader.onload function can see them.
 +         */
 +        var curFile = thisFile + 1;
 +        var lastFile = numbFiles;
 +
 +        // Get status area for this drop area
 +        statusArea = drop.siblings('.glm-imageUploadStatus');
 +
 +        // Make status area visible (overlay) and clear contents
 +        statusArea.html('');
 +
 +        // If file is an image
  // var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
  
  // if (regex.test(file.name.toLowerCase())) {
  
 -              // Create HTML5 file reader and load image
 -              var reader = new FileReader();
 -              reader.onload = function (e) {
 -              
 -                      // 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="";
 -                var sizeKB = file.size/1024;
 -                if(parseInt(sizeKB) > 1024)
 -                {
 -                    var sizeMB = sizeKB/1024;
 -                    sizeStr = sizeMB.toFixed(2)+" MB";
 +        // Create HTML5 file reader and load image
 +        var reader = new FileReader();
 +        reader.onload = function (e) {
 +
 +            // 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="";
 +            var sizeKB = file.size/1024;
 +            if(parseInt(sizeKB) > 1024)
 +            {
 +                var sizeMB = sizeKB/1024;
 +                sizeStr = sizeMB.toFixed(2)+" MB";
 +            }
 +            else
 +            {
 +                sizeStr = sizeKB.toFixed(2)+" KB";
 +            }
 +
 +            // 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);
 +
 +        this.setProgress = function(progress)
 +        {
 +            statusArea.find('.glm-progressBar').css('width', progress + '%');
 +        }
 +
 +        this.setAbort = function(jqxhr)
 +        {
 +            var sb = this.statusbar;
 +            $('#imageUploadCancel').click(function()
 +            {
 +                jqxhr.abort();
 +                sb.hide();
 +            });
 +        }
 +    }
 +
 +    /*
 +     * Sends file to image plugin via AJAX submission targeting WordPress AJAX
 +     * handler.
 +     */
 +    function sendFileToServer(fd, status)
 +    {
 +        // Send one (or more) images to the server. Normally only one image here for now.
 +        var jqXHR=$.ajax({
 +                xhr: function() {
 +                var xhrobj = $.ajaxSettings.xhr();
 +                if (xhrobj.upload) {
 +                        xhrobj.upload.addEventListener('progress', function(event) {
 +
 +                            // calculate progress periodically and set the progress bar
 +                            var percent = 0;
 +                            var position = event.loaded || event.position;
 +                            var total = event.total;
 +                            if (event.lengthComputable) {
 +                                percent = Math.ceil(position / total * 100);
 +                            }
 +                            status.setProgress(percent);
 +                        }, false);
 +
                  }
 -                else
 -                {
 -                    sizeStr = sizeKB.toFixed(2)+" KB";
 +                return xhrobj;
 +            },
 +            url: ajaxurl,
 +            type: "POST",
 +            contentType:false,
 +            processData: false,
 +            cache: false,
 +            data: fd,
 +            success: function(data){
 +
 +                // Parse returned data
 +                fileData = JSON.parse(data);
 +
 +                // Check for success
 +                if (fileData.status) {
 +
 +                    // Add image(s) to gallery display
-                     for (f of fileData.files) {
++                    for (var i = 0 ; i < fileData.files.length ; i++) {
 +
 +                        // 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);
++                        imageData = imageData.replace(/{ id }/g, fileData.files[i].id);
++                        imageData = imageData.replace(/\{ filename \}/g, fileData.files[i].newFileName);
 +                        galleryImages.prepend(imageData);
 +
 +                        // Enable the fields that were just added
-                         $("#" + f.id + " input, #" + f.id + " textarea").removeAttr('disabled');
++                        $("#" + fileData.files[i].id + " input, #" + fileData.files[i].id + " textarea").removeAttr('disabled');
 +
 +                        // Prepend image ID to position order input field
-                         $("#galleryPositionOrder").val(f.id + ',' + $("#galleryPositionOrder").val());
++                        $("#galleryPositionOrder").val(fileData.files[i].id + ',' + $("#galleryPositionOrder").val());
 +
 +                    }
 +
 +                } else {
 +                    alert("Upload Failed\nReason: " + fileData.message);
 +                    }
 +
 +                },
 +                complete: function() {
 +
 +                // When status area has faded
 +                statusArea.fadeOut( function() {
 +
 +                    // Process the next file, if one exists.
 +                    processFile();
 +
 +                });
 +
 +            }
 +        });
 +
 +        return jqXHR;
 +
 +    }
 +
 +    /*
 +     * This function is used to start handling of various things and
-      * to restart handling when an image has been added. I neede to
++     * to restart handling when an image has been added. I need to
 +     * do this because .on() didn't cover this situation.
 +     */
 +    function setupExpandedImageEvents() {
 +
++        var holdImage = false;
++        
 +        // Handle expanded images on hover for image gallery
 +        $('.glm-galleryImage').on("mouseenter", function(){
 +                id = $(this).attr("data-id");
++                
++                // If an image is being held, close it now and reset holdImage
++                if (holdImage) {
++                    $('#glm-galleryImageLarger_' + holdImage).dialog("close");
++                    holdImage = false;
+                 }
 -                      
 -                      // 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);
 -              
 -          this.setProgress = function(progress)
 -          {
 -              statusArea.find('.glm-progressBar').css('width', progress + '%');
 -          }
 -
 -          this.setAbort = function(jqxhr)
 -          {
 -              var sb = this.statusbar;
 -              $('#imageUploadCancel').click(function()
 -              {
 -                  jqxhr.abort();
 -                  sb.hide();
 -              });
 -          }       
 -      }
 -      
 -      /*
 -       * Sends file to image plugin via AJAX submission targeting WordPress AJAX
 -       * handler.
 -       */
 -      function sendFileToServer(fd, status)
 -      {
 -              // Send one (or more) images to the server. Normally only one image here for now.
 -          var jqXHR=$.ajax({
 -                  xhr: function() {
 -                  var xhrobj = $.ajaxSettings.xhr();
 -                  if (xhrobj.upload) {
 -                          xhrobj.upload.addEventListener('progress', function(event) {
 -
 -                              // calculate progress periodically and set the progress bar 
 -                              var percent = 0;
 -                              var position = event.loaded || event.position;
 -                              var total = event.total;
 -                              if (event.lengthComputable) {
 -                                  percent = Math.ceil(position / total * 100);
 -                              }
 -                              status.setProgress(percent);
 -                          }, false);
 -
 -                  }
 -                  return xhrobj;
 -              },      
 -              url: ajaxurl,
 -              type: "POST",
 -              contentType:false,
 -              processData: false,
 -              cache: false,
 -              data: fd,
 -              success: function(data){
 -
 -                              // 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\nReason: " + fileData.message);                                    
 -                              }
 -                      
 -              },
 -              complete: function() {
 -                      
 -                      // When status area has faded
 -                      statusArea.fadeOut( function() {
 -                              
 -                              // Process the next file, if one exists.
 -                              processFile();
 -                              
 -                      });
 -                       
 -              }
 -          }); 
 -          
 -          return jqXHR;
 -
 -      }
 -      
 -      /* 
 -       * This function is used to start handling of various things and
 -       * to restart handling when an image has been added. I neede to
 -       * do this because .on() didn't cover this situation.  
 -       */
 -      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");
 -          });
 -          
 -          // Make images sortable and store the list of IDs in a hidden input field when order has changed.
 -          $('.glm-galleryImages').sortable({
 -              update: function(event, ui) {
 -                      var sortedIDs = $(this).sortable('toArray');
 -                      $('#galleryPositionOrder').val(sortedIDs);
 -              }
 -          });
 -
 -      }
 -      setupExpandedImageEvents();
++                
++                // Display the larger image
 +                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"  }
 +                });
 +        });
++        // If an image is clicked, then hold the larter image dialog box
++        $('.glm-galleryImage').on("click", function(){
++            holdImage = $(this).attr("data-id");
++        });
 +        $('.glm-galleryImage').on("mouseleave", function(){
 +            id = $(this).attr("data-id");
-             $('#glm-galleryImageLarger_' + id).dialog("close");
-         });
-         // Make images sortable and store the list of IDs in a hidden input field when order has changed.
-         $('.glm-galleryImages').sortable({
-             update: function(event, ui) {
-                 var sortedIDs = $(this).sortable('toArray');
-                 $('#galleryPositionOrder').val(sortedIDs);
++            
++            // If the image has not been clicked to keep it displayed, close it now
++            if (!holdImage) {
++                $('#glm-galleryImageLarger_' + id).dialog("close");
 +            }
 +        });
 +
++        // Make images sortable and store the list of IDs in a hidden input field when order has changed.
++        if (enableDragable) {
++            $('.glm-galleryImages').sortable({
++                update: function(event, ui) {
++                    var sortedIDs = $(this).sortable('toArray');
++                    $('#galleryPositionOrder').val(sortedIDs);
++                }
++            });
++        }
 +    }
 +    setupExpandedImageEvents();
  });
@@@ -24,33 -23,16 +24,35 @@@ class EasyPasswor
          return $random;
      }
  
 -    // This is the function to produce the password
 -    function generateEasyPassword()
 -    {
 -        $word1 = $this->dictionaryWord();
 -        $numb = rand(1, 9);                                                  // Generate specified amount of numbers
 -        $word2 = $this->dictionaryWord();
 +    // Generate random capitalization - either all characters ('all')or just first and last ('firstlast')
 +    function randomCaps($s, $type = 'full') {
 +
 +        switch ($type) {
 +            case 'firstlast':
 +                if (rand(0, 1)) $s[0] = strtoupper($s[0]);
 +                $last = strlen($s) - 1;
 +                if (rand(0, 1)) $s[$last] = strtoupper($s[$last]);
 +                break;
 +            case 'all':
 +            default:
 +                for ($i = 0 ; $i < strlen($s) ; $i++) {
 +                    if (rand(0, 1)) $s[$i] = strtoupper($s[$i]);
 +                }
 +                break;
 +            }
 +        return $s;
 +    }
  
 -        $keys = array ($word1,$numb,$word2);                    // Place password components in an array
 -        $rand_keys = array_rand($keys,3);                                        // Randomize the 3 password components
 -        return $keys[$rand_keys[0]].$keys[$rand_keys[1]].$keys[$rand_keys[2]];  // Return the resulting password
 +    // This is the function to produce the password - optionally provide a type for capitalization
 +    function generateEasyPassword($type = 'firstlast')
 +    {
-         $numbPunct = '123456789!@#$%&_-:;.?/';
++        $numb = '123456789';
++        $punct = '#.-_,$%&!';
 +        $word1 = $this->randomCaps($this->dictionaryWord(), $type);
-         $char = $numbPunct[rand(0, strlen($numbPunct)-1)];
++        $numb = $numb[rand(0, strlen($numb)-1)];
++        $punct = $punct[rand(0, strlen($punct)-1)];
 +        $word2 = $this->randomCaps($this->dictionaryWord(), $type);
-         return $word1.$char.$word2;
++        return $word1.$punct.$word2.$numb;
      }
  
  
@@@ -1262,7 -1262,7 +1262,7 @@@ abstract class GlmDataAbstrac
  
              if ($d['count'] > 0) {
                  $this->inputFieldStatus = false;
--                $this->inputErrorReason = 'This must be unique, but it conflicts with another entry.';
++                $this->inputErrorReason = 'This value must be unique. The text you entered conflicts with another entry. Please try again.';
                  return $in;
              }
          }
                return $in;\r
        }\r
  \r
--      // Check min/max length\r
--      if (trim($in) != '' && $f['minLength'] && strlen($in) < $f['minLength']) {\r
--              $this->inputFieldStatus = false;\r
--              $this->inputErrorReason = 'Input is shorter than minimum length of '.$f['minLength'].' characters.';\r
--              return $in;\r
--      }\r
--      if (trim($in) != '' && $f['maxLength'] && strlen($in) > $f['maxLength']) {\r
--              $this->inputFieldStatus = false;\r
--              $this->inputErrorReason = 'Input is longer than maximum length of '.$f['maxLength'].' characters.';\r
--              return $in;\r
++      // Check min/max length
++      if (isset($f['minLength'])) {\r
++              if (trim($in) != '' && $f['minLength'] && strlen($in) < $f['minLength']) {\r
++                      $this->inputFieldStatus = false;\r
++                      $this->inputErrorReason = 'Input is shorter than minimum length of '.$f['minLength'].' characters.';\r
++                      return $in;\r
++              }
++      }
++      if (isset($f['maxLength'])) {\r
++              if (trim($in) != '' && $f['maxLength'] && strlen($in) > $f['maxLength']) {\r
++                      $this->inputFieldStatus = false;\r
++                      $this->inputErrorReason = 'Input is longer than maximum length of '.$f['maxLength'].' characters.';\r
++                      return $in;\r
++              }
        }
  
        // Check type of password
              $sql .= "ORDER BY $order
              ";
          }
--
++// echo "<pre>".print_r($sql,1)."</pre>";
          if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE && class_exists('glmMembersAdmin')) {
              glmMembersAdmin::addNotice($sql, 'DataBlock', "DataAbstract - getList() query");
          }
index 65242b3,65242b3..f344ef2
Binary files differ
index d6ac3f9,0000000..d9eb943
mode 100644,000000..100644
--- /dev/null
@@@ -1,790 -1,0 +1,795 @@@
-   
 +-- Gaslight Media Members Database 
 +-- File Created: 12/09/14 15:27:15
 +-- Database Version: 1.0.43
 +-- Database Creation Script
 +-- 
 +-- To permit each query below to be executed separately,
 +-- all queries must be separated by a line with four dashes
 +
 +-- Accommodation Types 
 +CREATE TABLE {prefix}accommodation_types (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  facility_type INT NULL,                   -- See "Facility Types" in config/plugin.ini
 +  name TINYTEXT NULL,                       -- Name of accommodation type
 +  descr TEXT NULL,                          -- Description of accommodation type
 +  short_descr TINYTEXT NULL,                -- Short description of accommodation type
 +  PRIMARY KEY (id),                         
 +  INDEX(facility_type),
 +  INDEX(name(20))
 +);
 +
 +----
 +
 +-- Accommodations
 +CREATE TABLE {prefix}accommodations (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- Accommodation record is active flag
 +  name TINYTEXT NULL,                       -- Name of the accommodation record
 +  accommodation_type INT NULL,              -- Pointer to Accommodation type in accommodation_types table
 +  descr TEXT NULL,                          -- Description of accommodation
 +  short_descr TINYTEXT NULL,                -- Short description of accommodation
 +  url TINYTEXT NULL,                        -- URL for info regarding this accommodation
 +  notes TEXT NULL,                          -- Notes regarding this accommodation - Not displayed on front-end
 +  create_time TIMESTAMP NULL,               -- Date/time this accommondation was created
 +  modify_time TIMESTAMP NULL,               -- Date/time this accommodation was last updated
 +  quant INT NULL,                           -- Quantity of this accommodation
 +  reservation_url TINYTEXT NULL,            -- URL to use for making reservaionn
 +  reservation_id TINYTEXT NULL,             -- ID to use as a reference to this accommodation when making reservations
 +  year_round TINYINT(1) NULL,               -- Accommodation is available year-round
 +  ref_type INT NULL,                        -- Type of entity this accommodation is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this accommodation is associated with
 +  PRIMARY KEY (id),
 +  INDEX(accommodation_type),
 +  INDEX(name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Accounts
 +CREATE TABLE {prefix}accounts (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  member INT NULL,
 +  payment_type INT NULL,
 +  invoice_delivery INT NULL,
 +  PRIMARY KEY (id),
 +  INDEX(member)
 +);
 +
 +----
 +
 +-- Activities
 +CREATE TABLE {prefix}activities (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- Activity is active flag
 +  activity_type INT NULL,                   -- ***** NEED TO ADD ACTIVITY_TYPES TABLE AND SUPPORT FOR THAT ***** 
 +  name TINYTEXT NULL,                       -- Activity name
 +  descr TEXT NULL,                          -- Description of activity
 +  short_descr TINYTEXT NULL,                -- Shot description of activity
 +  phone TINYTEXT NULL,                      -- Phone number to contact someone regarding this activity
 +  url TINYTEXT NULL,                        -- URL for info regarding this activity
 +  notes TEXT NULL,                          -- Notes regarding this activity - Not displayed on front-end
 +  create_time TIMESTAMP NULL,               -- Date/time this activity was created
 +  modify_time TIMESTAMP NULL,               -- Date/time this activity was last updated
 +  ref_type INT NULL,                        -- Type of entity this activity is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of type ref_type
 +  PRIMARY KEY (id),
 +  INDEX(activity_type),
 +  INDEX(name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Amenities
 +CREATE TABLE {prefix}amenities (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active TINYINT(1) NULL,                   -- Amenity is active flag
 +  name TINYTEXT NULL,                       -- Name of amenity
 +  descr TEXT NULL,                          -- Description of amenity
 +  short_descr TINYTEXT NULL,                -- Short description of amenity
 +  ref_type INT NULL,                        -- Type of entity these amenitites are associated with - see plugin.ini ref_type tables
 +  uses_value BOOLEAN NULL,                  -- Flag indicating whether the amenity requires a quantity number
 +  PRIMARY KEY (id),
 +  INDEX(name(20))
 +);
 +
 +----
 +
 +-- Amenity Reference - Links a specific amenity to a specific entity of type ref_type
 +CREATE TABLE {prefix}amenity_ref (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  amenity INT NULL,                         -- Pointer to amenity in amenities table
 +  ref_type INT NULL,                        -- Copy of ref_type from matching ameities table entry - to simplify searches
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of type ref_type
 +  amenity_value TINYTEXT NULL,              -- Quanity if amenity uses values
 +  PRIMARY KEY (id),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Member Cateogries - used with member information records
 +CREATE TABLE {prefix}categories (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Name of this category
 +  descr TEXT NULL,                          -- Description of this category
 +  short_descr TINYTEXT NULL,                -- Short description of this category 
 +  parent INT NULL,                          -- Pointer to parent category in this table - if there is one
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Mapping of categories to speific member information records
 +CREATE TABLE {prefix}category_member_info (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  category INT NULL,                        -- Pointer to category in categories table
 +  member_info INT NULL,                     -- Pointer to member infomation record
 +  PRIMARY KEY (id),
 +  CONSTRAINT {prefix}categories_fk_1
 +    FOREIGN KEY (category)
 +    REFERENCES {prefix}categories (id)
 +    ON DELETE CASCADE,
 +  INDEX(category),
 +  INDEX(member_info)
 +);
 +
 +----
 +
 +-- Cities
 +CREATE TABLE {prefix}cities (
 +  id INT NOT NULL AUTO_INCREMENT,           
 +  name TINYTEXT NULL,                       -- Name of city
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Contacts - used by various entities
 +CREATE TABLE {prefix}contacts (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- Contact is active flag
-   status TINYINT(1) NULL,                   -- Display/Use status - See plugin.ini status table 
++  access INT NULL,                          -- Access type - See access table in plugin.ini
 +  fname TINYTEXT NULL,                      -- First name of contact
 +  lname TINYTEXT NULL,                      -- Last name of contact
 +  contact_type INT NULL,                    -- Contact type - see contact_type table (individual, role, ...)
 +  contact_role INT NULL,                    -- Contact WordPress user Role
 +  org TINYTEXT NULL,                        -- Organization name
++  title TINYTEXT NULL,                      -- Title/Position
++  descr TEXT NULL,                          -- Description of position/responsibilities - Displayed
++  image TINYTEXT NULL,                      -- Image
 +  addr1 TINYTEXT NULL,                      -- Address line 1 - Address is for contact, not necessarily for organization
 +  addr2 TINYTEXT NULL,                      -- Address line 2 
 +  city INT NULL,                            -- Pointer to city in cities table
 +  state TINYTEXT NULL,                      -- Two character state code - matches states.ini entries
 +  country TINYTEXT NULL,                    -- Two character country code - matches countries.ini entries 
 +  zip TINYTEXT NULL,                        -- ZIP/Postal Code     
 +  lat FLOAT NULL,                           -- Latitude of contact location
 +  lon FLOAT NULL,                           -- Longitude of contact location
 +  url TINYTEXT NULL,                        -- URL to information regarding this contact
 +  office_phone TINYTEXT NULL,               -- Office phone number
 +  home_phone TINYTEXT NULL,                 -- Home phone number - or after-hours phone number
 +  mobile_phone TINYTEXT NULL,               -- Mobile phone number
 +  alt_phone TINYTEXT NULL,                  -- An alternate phone number
 +  fax TINYTEXT NULL,                        -- FAX number (do people still use these?) 
 +  email TINYTEXT NULL,                      -- E-Mail address
 +  alt_email TINYTEXT NULL,                  -- Alternate E-Mail address - Also used to log-in 
 +  username TINYTEXT NULL,                   -- Optional username to use for login
 +  password TINYTEXT NULL,                   -- Encrypted password
 +  notes TEXT NULL,                          -- Notes - Not displayed on front-end
 +  create_time TIMESTAMP NULL,               -- Create date/time
 +  modify_time TIMESTAMP NULL,               -- Last modified date/time
 +  ref_type INT NULL,                        -- Type of entity this contact is associated with                        
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this contact is associated with
 +  PRIMARY KEY (id),
 +  INDEX(fname(20)),
 +  INDEX(lname(20)),
 +  INDEX(city),
 +  INDEX(zip(10)),
 +  INDEX(lat),
 +  INDEX(lon),
 +  INDEX(email(20))
 +);
 +
 +----
 +
 +-- Facilities - Facilities are separate functional units of a member, either physically or operationally
 +-- For example, separate facilities could be individual properties (hotels, motels) or could be operationally 
 +-- separate hotel and restaurant at the same location. A facility is an entity under a member "location".
 +CREATE TABLE {prefix}facilities (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- Facility is active flag
 +  facility_type INT NULL,                   -- Facility type - see plugin.ini facility type
 +  location INT NULL,                        -- Pointer to one of the member's locations - see locations table
 +  name TINYTEXT NULL,                       -- Name of this facility
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short description
 +  addr1 TINYTEXT NULL,                      -- Address line 1 
 +  addr2 TINYTEXT NULL,                      -- Address line 2
 +  city INT NULL,                            -- Pointer to city in cities table
 +  state TINYTEXT NULL,                      -- Two character state code - matches states.ini entries
 +  country TINYTEXT NULL,                    -- Two character country code - matches countries.ini entries 
 +  zip TINYTEXT NULL,                        -- ZIP/Postal code
 +  lat FLOAT NULL,                           -- Latitude of facility
 +  lon FLOAT NULL,                           -- Longitude of facility
 +  phone TINYTEXT NULL,                      -- Primary phone number
 +  toll_free TINYTEXT NULL,                  -- Toll Free phone number
 +  url TINYTEXT NULL,                        -- URL for information specifically regarding this facility
 +  logo TINYTEXT NULL,                       -- Logo 
 +  notes TEXT NULL,                          -- Notes - Not displayed on front-end
 +  create_time TIMESTAMP NULL,               -- Create date/time
 +  modify_time TIMESTAMP NULL,               -- Last modified date/time
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(city),
 +  INDEX(zip(10)),
 +  INDEX(lat),
 +  INDEX(lon)
 +);
 +
 +----
 +
 +-- Donwloadable Files - files are stored under /wp-content/uploads/glm-member-db/files/
 +CREATE TABLE {prefix}files (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Name of this file
 +  file_name TINYTEXT NULL,                  -- Physical file name for this file
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short descroption
 +  size INT NULL,                            -- Download size of this file
 +  pending BOOLEAN NULL,                     -- File is pending review flag
 +  create_date DATE NULL,                    -- Date file was uploaded
 +  ref_type INT NULL,                        -- Type of entity this file is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this file is associated with
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(file_name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Detail on golf courses
 +CREATE TABLE {prefix}golf (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- This golf course is active flag
 +  name TINYTEXT NULL,                       -- Name of Golf course
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short Description
 +  rating TINYTEXT NULL,                     -- Rating
 +  par TINYTEXT NULL,                        -- Par
 +  yardage TINYTEXT NULL,                    -- Total yardage
 +  slope TINYTEXT NULL,                      -- Slope rating
 +  walking TINYINT(1) NULL,                  -- Walking course
 +  holes INT NULL,                           -- Number of holes
 +  reservation_url TINYTEXT NULL,            -- URL for making reservations for this course
 +  ref_type INT NULL,                        -- Type of entity this golf course is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this golf course is associated with
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Images - Images are stored under /wp-content/uploads/glm-member-db/images/{size}/
 +CREATE TABLE {prefix}images (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Original name of the image - might be URL if copied via HTTP
-   access INT NULL,                          -- Access type - See memb_access table in plugin.ini
++  status TINYINT(1) NULL,                   -- Display/Use status - See plugin.ini status table
++  selected_image BOOLEAN NULL,               -- A single special image in the current gallery for this entity
++  featured_image BOOLEAN null,              -- Image is a member of a group of featured images
 +  file_name TINYTEXT NULL,                  -- Stored file name for the image
 +  descr TEXT NULL,                          -- Description 
 +  caption TINYTEXT NULL,                    -- Caption for the image
 +  position INT NULL,                        -- Numeric position for sequence of display
 +  ref_type INT NULL,                        -- Type of entity this image is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this image is associated with
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(file_name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- Member locations - Locations are physically separate campuses where facilities exist
 +CREATE TABLE {prefix}locations (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- This location is active flag
 +  member INT NULL,                          -- Pointer to main member record
 +  member_info INT NULL,                     -- Pointer to associated member info record
 +  name TINYTEXT NULL,                       -- Name of location 
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short Description
 +  addr1 TINYTEXT NULL,                      -- Address line 1 - Main address for this location
 +  addr2 TINYTEXT NULL,                      -- Address line 2
 +  city INT NULL,                            -- Pointer to city in cities table
 +  state TINYTEXT NULL,                      -- Two character state code - matches states.ini entries
 +  country TINYTEXT NULL,                    -- Two character country code - matches countries.ini entries 
 +  zip TINYTEXT NULL,                        -- ZIP/Postal code
 +  lat FLOAT NULL,                           -- Latitude of location
 +  lon FLOAT NULL,                           -- Longitude of location
 +  region INT NULL,                          -- Pointer to region where location exists
 +  phone TINYTEXT NULL,                      -- Primary phone number
 +  toll_free TINYTEXT NULL,                  -- Toll Free phone number
 +  url TINYTEXT NULL,                        -- URL for information regarding this location
 +  logo TINYTEXT NULL,                       -- Logo
 +  notes TEXT NULL,                          -- Notes - not displayed on front-end
 +  create_time TIMESTAMP NULL,               -- Create date/time
 +  modify_time TIMESTAMP NULL,               -- Last Update date/time
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(city),
 +  INDEX(zip(10)),
 +  INDEX(lat),
 +  INDEX(lon),
 +  INDEX(region)
 +);
 +
 +----
 +
 +-- Meals offered by a restaurant
 +CREATE TABLE {prefix}meals (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- Meal is active flag
 +  name TINYTEXT NULL,                       -- Name of this meal (typically Breakfast, Lunch, Dinner, Brunch, ...)
 +  descr TEXT NULL,                          -- Description of the meal
 +  short_descr TINYTEXT NULL,                -- Short description
 +  menu TEXT NULL,                           -- Text menu for this meal
 +  menu_file TINYTEXT NULL,                  -- File name of downloadable menu file (PDF, etc.)
 +  daily BOOLEAN NULL,                       -- Flag indicating if meal is available daily
 +  daily_start_time TIME NULL,               -- Daily meal - Time of day this meal starts
 +  daily_end_time TIME NULL,                 -- Daily meal - Time of day this meal ends
 +  daily_res_req BOOLEAN NULL,               -- Daily meal - Reservations requested
 +  sunday BOOLEAN NULL,                      -- Flag indicating if meal is available Sunday
 +  sun_menu TEXT NULL,                       -- Optional menu text for Sunday
 +  sun_start_time TIME NULL,                 -- Sunday - Time of day this meal starts
 +  sun_end_time TIME NULL,                   -- Sunday - Time of day this meal ends
 +  sun_res_req BOOLEAN NULL,                 -- Sunday - Reservations requested
 +  monday BOOLEAN NULL,                      -- Flag indicating if meal is available Monday
 +  mon_menu TEXT NULL,                       -- Optional menu text for Monday
 +  mon_start_time TIME NULL,                 -- Monday - Time of day this meal starts
 +  mon_end_time TIME NULL,                   -- Monday - Time of day this meal ends
 +  mon_res_req BOOLEAN NULL,                 -- Monday - Reservations requested
 +  tuesday BOOLEAN NULL,                     -- Flag indicating if meal is available Tuesday
 +  tue_menu TEXT NULL,                       -- Optional menu text for Tuesday
 +  tue_start_time TIME NULL,                 -- Tuesday - Time of day this meal starts
 +  tue_end_time TIME NULL,                   -- Tuesday - Time of day this meal ends
 +  tue_res_req BOOLEAN NULL,                 -- Tuesday - Reservations requested
 +  wednesday BOOLEAN NULL,                   -- Flag indicating if meal is available Wednesday
 +  wed_menu TEXT NULL,                       -- Optional menu text for Wednesday
 +  wed_start_time TIME NULL,                 -- Wednesday - Time of day this meal starts
 +  wed_end_time TIME NULL,                   -- Wednesday - Time of day this meal ends
 +  wed_res_req BOOLEAN NULL,                 -- Wednesday - Reservations requested
 +  thursday BOOLEAN NULL,                    -- Flag indicating if meal is available Thursday
 +  thu_menu TEXT NULL,                       -- Optional menu text for Thursday
 +  thu_start_time TIME NULL,                 -- Thursday - Time of day this meal starts
 +  thu_end_time TIME NULL,                   -- Thursday - Time of day this meal ends
 +  thu_res_req BOOLEAN NULL,                 -- Thursday - Reservations requested
 +  friday BOOLEAN NULL,                      -- Flag indicating if meal is available Friday
 +  fri_menu TEXT NULL,                       -- Optional menu text for Friday
 +  fri_start_time TIME NULL,                 -- Friday - Time of day this meal starts
 +  fri_end_time TIME NULL,                   -- Friday - Time of day this meal ends
 +  fri_res_req BOOLEAN NULL,                 -- Friday - Reservations requested
 +  saturday BOOLEAN NULL,                    -- Flag indicating if meal is available Saturday
 +  sat_menu TEXT NULL,                       -- Optional menu text for Saturday
 +  sat_start_time TIME NULL,                 -- Saturday - Time of day this meal starts
 +  sat_end_time TIME NULL,                   -- Saturday - Time of day this meal ends
 +  sat_res_req BOOLEAN NULL,                 -- Saturday - Reservations requested
 +  restaurant INT NULL,                      -- Pointer to restaurant that has this meal
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(restaurant)
 +);
 +
 +----
 +
 +-- Primary member records - One for each member
 +CREATE TABLE {prefix}members (
 +  id INT NOT NULL AUTO_INCREMENT,
-     'Add Member',         
++  access INT NULL,                          -- Access type - See access table in plugin.ini
 +  member_type INT NULL,                     -- Pointer to member type in member_type table
 +  created DATE NULL,                        -- Date member record was created
 +  name TINYTEXT NULL,                       -- Member name
 +  member_slug TINYTEXT NULL,                -- Member name slug for canonical URLs (lowercase, "-" for spaces, no punctuation)
 +  PRIMARY KEY (id),
 +  INDEX(name(20)),
 +  INDEX(member_slug(20)),
 +  INDEX(created)
 +);
 +
 +----
 +
 +-- Member information version record - May be multiples per member - Only one with stauts "Active" for a distinct date range
 +CREATE TABLE {prefix}member_info (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  member INT NULL,                          -- Pointer to member record in table members
 +  member_name TINYTEXT NULL,                -- Copy of member name from members table entry for fast reference
 +  status INT NULL,                          -- Status of this member information record - See plugin.ini status table
 +  reference_name TINYTEXT NULL,             -- Refernce name for this member information record - Not displayed on front-end
 +  descr TEXT NULL,                          -- Description
 +  short_descr TEXT NULL,                    -- Short description
 +  addr1 TINYTEXT NULL,                      -- Address line 1 - Main member address (main location) or 
 +  addr2 TINYTEXT NULL,                      -- Address line 2
 +  city INT NULL,                            -- Pointer to City in cities table
 +  state TINYTEXT NULL,                      -- Two character state code - matches states.ini entries
 +  country TINYTEXT NULL,                    -- Two character country code - matches countries.ini entries
 +  zip TINYTEXT NULL,                        -- ZIP/Postal code
 +  lat FLOAT NULL,                           -- Latitude of member's location
 +  lon FLOAT NULL,                           -- Longitude of member's location
 +  region INT NULL,                          -- Pointer to entry in regions table
 +  phone TINYTEXT NULL,                      -- Primary phone number
 +  toll_free TINYTEXT NULL,                  -- Toll Free phone number
 +  url TINYTEXT NULL,                        -- URL with information about this member
 +  email TINYTEXT NULL,                      -- Main E-Mail address for this member
 +  logo TINYTEXT NULL,                       -- Member logo
 +  cc_type INT NULL,                         -- Bitmap of credit card types accepted - See credit_card array in plugin.ini
 +  notes TEXT NULL,                          -- General notes - Not displayed in front-end
 +  create_time TIMESTAMP NULL,               -- Create date/time
 +  modify_time TIMESTAMP NULL,               -- Last update date/time
 +  PRIMARY KEY (id),
 +  INDEX(status),
 +  INDEX(city),
 +  INDEX(zip(10)),
 +  INDEX(lat),
 +  INDEX(lon),
 +  INDEX(region)
 +);
 +
 +----
 +
 +-- Member type - Can be used to assign members to different "classes" of membership (i.e. Full, Associate, Premium)
 +-- Mostly for internal use by the member organization, but could be displayed - Consider a short_description if they are. 
 +CREATE TABLE {prefix}member_type (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Name of member type
 +  descr TINYTEXT NULL,                      -- Description of member type
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Regions - Used to segment members into various geographical regions - can be cities, counties, or other logical regions
 +CREATE TABLE {prefix}regions (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Name of region
 +  descr TEXT NULL,                          -- Descrption of region
 +  short_descr TINYTEXT NULL,                -- Short descroption of region
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Resturaunt Types - Various general types of restaurants (i.e. Fast Food, Ethnic, Fine food, ...)
 +CREATE TABLE {prefix}restaurant_types (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                       -- Name of restaurant type
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short Description
 +  PRIMARY KEY (id),
 +  INDEX(name(20))
 +);
 +
 +----
 +
 +-- Restaurants
 +CREATE TABLE {prefix}restaurants (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  active BOOLEAN NULL,                      -- This restaurant is active flag
 +  name TINYTEXT NULL,                       -- Name of restaurant
 +  restaurant_type INT NULL,                 -- Pointer to restaurant_types table entry
 +  descr TEXT NULL,                          -- Description
 +  short_descr TINYTEXT NULL,                -- Short Description
 +  url TINYTEXT NULL,                        -- URL of Web page about this restaurant
 +  reservation_url TINYTEXT NULL,            -- Reservations URL 
 +  phone TINYTEXT NULL,                      -- Phone number / reservations number
 +  hours_descr TINYTEXT NULL,                -- Description of restaurant hours
 +  alcohol BOOLEAN NULL,                     -- Flag indicating whether restaurant serves alcohol 
 +  non_smoking BOOLEAN NULL,                 -- Flag indicating whether restaurant is non-smoking only
 +  notes TEXT NULL,                          -- General notes
 +  ref_type INT NULL,                        -- Type of entity this restaurant is associated with
 +  ref_dest INT NULL,                        -- Pointer to the specific entity of ref_type this restaurant is associated with
 +  PRIMARY KEY (id),
 +  INDEX(restaurant_type),
 +  INDEX(name(20)),
 +  INDEX(ref_type),
 +  INDEX(ref_dest)
 +);
 +
 +----
 +
 +-- General settings available on Management page in admin - Only 1 entry in this table
 +-- Items in this table should be all self-explanatory
 +CREATE TABLE {prefix}settings_general (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  admin_debug BOOLEAN DEFAULT '1',
 +  admin_debug_verbose BOOLEAN DEFAULT '0',
 +  front_debug BOOLEAN DEFAULT '0',
 +  front_debug_verbose BOOLEAN DEFAULT '0',
 +  google_maps_api_key TINYTEXT DEFAULT '',
 +  maps_default_lat FLOAT DEFAULT '45.3749',
 +  maps_default_lon FLOAT DEFAULT '-84.9592',
 +  maps_default_zoom INTEGER DEFAULT '10',
 +  time_zone TINYTEXT DEFAULT NULL,
 +  canonical_member_page TINYTEXT DEFAULT NULL,
 +  list_show_map BOOLEAN DEFAULT '1',
 +  list_show_list BOOLEAN DEFAULT '1',
 +  list_show_search BOOLEAN DEFAULT '1',
 +  list_show_search_text BOOLEAN DEFAULT '1',
 +  list_show_search_category BOOLEAN DEFAULT '1',
 +  list_show_search_amenities BOOLEAN DEFAULT '1',
 +  list_show_search_alpha BOOLEAN DEFAULT '1',
 +  list_show_detail_link BOOLEAN DEFAULT '1',
 +  list_show_logo BOOLEAN DEFAULT '1',
 +  list_logo_size TINYTEXT NULL,
 +  list_show_address BOOLEAN DEFAULT '1',
 +  list_show_street BOOLEAN DEFAULT '1',
 +  list_show_citystatezip BOOLEAN DEFAULT '1',
 +  list_show_country BOOLEAN DEFAULT '1',
 +  list_show_region BOOLEAN DEFAULT '1',
 +  list_show_descr BOOLEAN DEFAULT '0',
 +  list_show_short_descr BOOLEAN DEFAULT '1',
 +  list_show_phone BOOLEAN DEFAULT '1',
 +  list_show_tollfree BOOLEAN DEFAULT '1',
 +  list_show_url BOOLEAN DEFAULT '1',
 +  list_show_url_newtarget BOOLEAN DEFAULT '1',
 +  list_show_email BOOLEAN DEFAULT '1',
 +  list_show_categories BOOLEAN DEFAULT '1',
 +  list_show_creditcards BOOLEAN DEFAULT '1',
 +  list_show_amenities BOOLEAN DEFAULT '0',
 +  list_map_show_detaillink BOOLEAN DEFAULT '1',
 +  list_map_show_logo BOOLEAN DEFAULT '0',
 +  list_map_logo_size TINYTEXT NULL,
 +  list_map_show_descr BOOLEAN DEFAULT '0',
 +  list_map_show_short_descr BOOLEAN DEFAULT '1',
 +  list_map_show_address BOOLEAN DEFAULT '1',
 +  list_map_show_street BOOLEAN DEFAULT '1',
 +  list_map_show_citystatezip BOOLEAN DEFAULT '1',
 +  list_map_show_country BOOLEAN DEFAULT '1',
 +  list_map_show_region BOOLEAN DEFAULT '1',
 +  list_map_show_phone BOOLEAN DEFAULT '1',
 +  list_map_show_tollfree BOOLEAN DEFAULT '1',
 +  list_map_show_url BOOLEAN DEFAULT '1',
 +  list_map_show_url_newtarget BOOLEAN DEFAULT '1',
 +  list_map_show_email BOOLEAN DEFAULT '1',
 +  list_map_show_categories BOOLEAN DEFAULT '0',
 +  list_map_show_creditcards BOOLEAN DEFAULT '0',
 +  list_map_show_amenities BOOLEAN DEFAULT '0',
 +  detail_show_map BOOLEAN DEFAULT '1',
 +  detail_show_directions BOOLEAN DEFAULT '1',
 +  detail_show_logo BOOLEAN DEFAULT '1',
 +  detail_logo_size TINYTEXT NULL,
 +  detail_show_descr BOOLEAN DEFAULT '1',
 +  detail_show_short_descr BOOLEAN DEFAULT '0',
 +  detail_show_address BOOLEAN DEFAULT '1',
 +  detail_show_street BOOLEAN DEFAULT '1',
 +  detail_show_citystatezip BOOLEAN DEFAULT '1',
 +  detail_show_country BOOLEAN DEFAULT '1',
 +  detail_show_region BOOLEAN DEFAULT '1',
 +  detail_show_phone BOOLEAN DEFAULT '1',
 +  detail_show_tollfree BOOLEAN DEFAULT '1',
 +  detail_show_url BOOLEAN DEFAULT '1',
 +  detail_show_url_newtarget BOOLEAN DEFAULT '1',
 +  detail_show_email BOOLEAN DEFAULT '1',
 +  detail_show_categories BOOLEAN DEFAULT '1',
 +  detail_show_creditcards BOOLEAN DEFAULT '1',
 +  detail_show_amenities BOOLEAN DEFAULT '1',
 +  detail_show_imagegallery BOOLEAN DEFAULT '1',
 +  detail_show_coupons BOOLEAN DEFAULT '0',
 +  detail_show_packages BOOLEAN DEFAULT '0',
 +  detail_map_show_logo BOOLEAN DEFAULT '0',
 +  detail_map_logo_size TINYTEXT NULL,
 +  detail_map_show_descr BOOLEAN DEFAULT '0',
 +  detail_map_show_short_descr BOOLEAN DEFAULT '1',
 +  detail_map_show_address BOOLEAN DEFAULT '1',
 +  detail_map_show_street BOOLEAN DEFAULT '1',
 +  detail_map_show_citystatezip BOOLEAN DEFAULT '1',
 +  detail_map_show_country BOOLEAN DEFAULT '1',
 +  detail_map_show_region BOOLEAN DEFAULT '1',
 +  detail_map_show_phone BOOLEAN DEFAULT '1',
 +  detail_map_show_tollfree BOOLEAN DEFAULT '1',
 +  detail_map_show_url BOOLEAN DEFAULT '1',
 +  detail_map_show_url_newtarget BOOLEAN DEFAULT '1',
 +  detail_map_show_email BOOLEAN DEFAULT '1',
 +  detail_map_show_categories BOOLEAN DEFAULT '0',
 +  detail_map_show_creditcards BOOLEAN DEFAULT '0',
 +  detail_map_show_amenities BOOLEAN DEFAULT '0',
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Set default entry
 +INSERT INTO {prefix}settings_general
 +    ( id, time_zone, canonical_member_page )
 +   VALUES
 +    ( 1, 'America/Detroit', 'member-detail' )
 +;
 +
 +----
 +
 +-- Terms used in site modifiable on Management page in admin - Only 1 entry in this table
 +-- Tems in this table should be all self-explanatory
 +CREATE TABLE {prefix}settings_terms (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  term_admin_menu_members TINYTEXT NULL,
 +  term_admin_menu_member_list TINYTEXT NULL,
 +  term_admin_menu_member TINYTEXT NULL,
 +  term_admin_menu_configure TINYTEXT NULL,
 +  term_admin_menu_settings TINYTEXT NULL,
 +  term_admin_menu_shortcodes TINYTEXT NULL,
 +  term_admin_menu_members_dashboard TINYTEXT NULL,
 +  term_admin_menu_members_list TINYTEXT NULL,
 +  term_admin_menu_members_reports TINYTEXT NULL,
 +  term_admin_menu_member_dashboard TINYTEXT NULL,
 +  term_admin_menu_member_info TINYTEXT NULL,
 +  term_admin_menu_member_locations TINYTEXT NULL,
 +  term_admin_menu_member_facilities TINYTEXT NULL,
 +  term_admin_menu_member_attractions TINYTEXT NULL,
 +  term_admin_menu_member_contacts TINYTEXT NULL,
 +  term_admin_menu_configure_member_types TINYTEXT NULL,
 +  term_admin_menu_configure_member_cats TINYTEXT NULL,
 +  term_admin_menu_configure_accom_types TINYTEXT NULL,
 +  term_admin_menu_configure_amenities TINYTEXT NULL,
 +  term_admin_menu_configure_cities TINYTEXT NULL,
 +  term_admin_menu_configure_regions TINYTEXT NULL,
 +  term_admin_menu_settings_general TINYTEXT NULL,
 +  term_admin_menu_settings_terms TINYTEXT NULL,
 +  term_admin_menu_settings_development TINYTEXT NULL,
 +  term_member TINYTEXT NULL,
 +  term_member_cap TINYTEXT NULL,
 +  term_member_plur TINYTEXT NULL,
 +  term_member_plur_cap TINYTEXT NULL,
 +  term_location TINYTEXT NULL,
 +  term_location_cap TINYTEXT NULL,
 +  term_location_plur TINYTEXT NULL,
 +  term_location_plur_cap TINYTEXT NULL,
 +  term_facility TINYTEXT NULL,
 +  term_facility_cap TINYTEXT NULL,
 +  term_facility_plur TINYTEXT NULL,
 +  term_facility_plur_cap TINYTEXT NULL,
 +  term_attraction TINYTEXT NULL,
 +  term_attraction_cap TINYTEXT NULL,
 +  term_attraction_plur TINYTEXT NULL,
 +  term_attraction_plur_cap TINYTEXT NULL,
 +  term_contact TINYTEXT NULL,
 +  term_contact_cap TINYTEXT NULL,
 +  term_contact_plur TINYTEXT NULL,
 +  term_contact_plur_cap TINYTEXT NULL,
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Default terms entry
 +INSERT INTO {prefix}settings_terms
 +    (
 +    id,
 +    term_admin_menu_members,                        
 +    term_admin_menu_member_list,                    
 +    term_admin_menu_member,                     
 +    term_admin_menu_configure,                      
 +    term_admin_menu_settings,                       
 +    term_admin_menu_shortcodes,                     
 +    term_admin_menu_members_dashboard,         
 +    term_admin_menu_members_list,                   
 +    term_admin_menu_members_reports,                
 +    term_admin_menu_member_dashboard,
 +    term_admin_menu_member_info,
 +    term_admin_menu_member_locations,               
 +    term_admin_menu_member_facilities,              
 +    term_admin_menu_member_attractions,             
 +    term_admin_menu_member_contacts,                
 +    term_admin_menu_configure_member_types,         
 +    term_admin_menu_configure_member_cats,          
 +    term_admin_menu_configure_accom_types,          
 +    term_admin_menu_configure_amenities,     
 +    term_admin_menu_configure_cities,               
 +    term_admin_menu_configure_regions,              
 +    term_admin_menu_settings_general,               
 +    term_admin_menu_settings_terms,                 
 +    term_admin_menu_settings_development,           
 +    term_member,                                    
 +    term_member_cap,                                
 +    term_member_plur,                               
 +    term_member_plur_cap,                           
 +    term_location,                                  
 +    term_location_cap,                              
 +    term_location_plur,                             
 +    term_location_plur_cap,                         
 +    term_facility,                                  
 +    term_facility_cap,                              
 +    term_facility_plur,                             
 +    term_facility_plur_cap,                         
 +    term_attraction,                                
 +    term_attraction_cap,                            
 +    term_attraction_plur,                           
 +    term_attraction_plur_cap,                       
 +    term_contact,                                   
 +    term_contact_cap,                               
 +    term_contact_plur,                              
 +    term_contact_plur_cap                           
 +    )
 +   VALUES
 +    (
 +    1,
 +    'Members',            
 +    'Member',             
++    'Member',         
 +    'Configure',          
 +    'Management',           
 +    'Shortcodes',         
 +    'Dashboard',          
 +    'Member List',        
 +    'Reports',            
 +    'Member Dashboard',
 +    'Member Info',        
 +    'Locations',          
 +    'Facilities',         
 +    'Attractions',        
 +    'Contacts',           
 +    'Member Types',       
 +    'Member Categories',  
 +    'Accommodation Types',
 +    'Amenities',          
 +    'Cities',             
 +    'Regions',            
 +    'General Settings',   
 +    'Terms & Phrases',    
 +    'Development',        
 +    'member',             
 +    'Member',             
 +    'members',            
 +    'Members',            
 +    'location',           
 +    'Location',           
 +    'locations',          
 +    'Locations',          
 +    'facility',           
 +    'Facility',           
 +    'facilities',         
 +    'Facilities',         
 +    'attraction',         
 +    'Attraction',         
 +    'attractions',        
 +    'Attractions',        
 +    'contact',            
 +    'Contact',            
 +    'contacts',           
 +    'Contacts'
 +    )
 +;
 +
 +----
 +
 +-- Social Media types (i.e. Facebook, Twitter, ...)
 +CREATE TABLE {prefix}social_media (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  name TINYTEXT NULL,                                   -- Name of this social media service
 +  descr TEXT NULL,                                      -- Description
 +  short_descr TINYTEXT NULL,                            -- Short Description
 +  PRIMARY KEY (id)
 +);
 +
 +----
 +
 +-- Social media to entity cross-reference table
 +CREATE TABLE {prefix}social_media_ref (
 +  id INT NOT NULL AUTO_INCREMENT,
 +  ref_type INT NULL,                                    -- Type of entity this entry is associated with
 +  ref_dest INT NULL,                                    -- Pointer to the specific entity of ref_type
 +  social_media INT NULL,                                -- Pointer to entry in social_media table
 +  url TINYTEXT NULL,                                    -- URL to this social media service
 +  PRIMARY KEY (id),
 +  INDEX(ref_type),
 +  INDEX(ref_dest),
 +  INDEX(social_media)
 +);
index 7a07b1c,0000000..921f4bd
mode 100644,000000..100644
--- /dev/null
@@@ -1,205 -1,0 +1,209 @@@
- CREATE TABLE {prefix}contact_permissions (
-   id INT NOT NULL AUTO_INCREMENT,
-   permission INT NULL, 
-   contact INT NULL,
-   PRIMARY KEY (id),
-   CONSTRAINT {prefix}contact_fk_1
-     FOREIGN KEY (contact)
-     REFERENCES {prefix}contacts (id)
-     ON DELETE CASCADE,
-   INDEX(permission),
-   INDEX(contact)
- );
- ----
 +-- Gaslight Media Members Database 
 +-- File Created: 12/09/14 15:27:15
 +-- Database Version: 1.0.28
 +-- Database Update From Previous Version Script
 +-- 
 +-- To permit each query below to be executed separately,
 +-- all queries must be separated by a line with four dashses
 +
 +RENAME TABLE {prefix}activties to {prefix}activities;
 +
 +----
 +
- DROP TABLE {prefix}contact_permissions IF EXISTS;
 +ALTER TABLE {prefix}contacts ADD COLUMN username TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}activities DROP COLUMN facility;
 +
 +----
 +
 +ALTER TABLE {prefix}accommodations ADD COLUMN url TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}accommodations ADD COLUMN notes TEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}accommodations ADD COLUMN create_time TIMESTAMP;
 +
 +----
 +
 +ALTER TABLE {prefix}accommodations ADD COLUMN modify_time TIMESTAMP;
 +
 +----
 +
 +ALTER TABLE {prefix}contacts MODIFY state TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}contacts MODIFY country TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}contacts DROP COLUMN permissions;
 +
 +----
 +
 +ALTER TABLE {prefix}facilities MODIFY state TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}facilities MODIFY country TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}files MODIFY pending BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}locations DROP COLUMN location_type;
 +
 +----
 +
 +ALTER TABLE {prefix}locations ADD COLUMN member_info INT;
 +
 +----
 +
 +ALTER TABLE {prefix}locations MODIFY state TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}locations MODIFY country TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}meals ADD COLUMN menu_file TINYTEXT;
 +
 +----
 +
 +ALTER TABLE {prefix}meals DROP COLUMN special_menu;
 +
 +----
 +
 +ALTER TABLE {prefix}meals DROP COLUMN daily_time;
 +
 +----
 +
 +ALTER TABLE {prefix}meals ADD COLUMN daily BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY daily_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY sunday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY sun_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY monday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY tuesday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY wednesday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY thursday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY friday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY saturday BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY mon_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY tue_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY wed_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY thu_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY fri_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals MODIFY sat_res_req BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}meals DROP COLUMN ref_type;
 +
 +----
 +
 +ALTER TABLE {prefix}meals DROP COLUMN ref_dest;
 +
 +----
 +
 +CREATE INDEX meal_restaurant ON {prefix}meals (restaurant);
 +
 +----
 +
 +ALTER TABLE {prefix}restaurant_types DROP COLUMN active;
 +
 +----
 +
 +ALTER TABLE {prefix}restaurants DROP COLUMN menu;
 +
 +----
 +
 +ALTER TABLE {prefix}restaurants DROP COLUMN special_menu;
 +
 +----
 +
 +ALTER TABLE {prefix}restaurants MODIFY alcohol BOOLEAN;
 +
 +----
 +
 +ALTER TABLE {prefix}restaurants MODIFY non_smoking BOOLEAN;
 +
 +----
 +
- ALTER TABLE {prefix}contacts ADD COLUMN contact_role INT;
++ALTER TABLE {prefix}contacts ADD COLUMN contact_role INT;
 +
 +----
 +
++ALTER TABLE {prefix}contacts ADD COLUMN access int null;
++
++----
++
++ALTER TABLE {prefix}contacts ADD COLUMN title tinytext null;
++
++----
++
++ALTER TABLE {prefix}contacts ADD COLUMN descr text null;
++
++----
++
++ALTER TABLE {prefix}contacts ADD COLUMN image tinytext null;
++
++----
++
++ALTER TABLE {prefix}images ADD COLUMN selected BOOLEAN null;
++
++----
 +
++ALTER TABLE {prefix}images ADD COLUMN featured BOOLEAN null;
index 291462a,0000000..27ee536
mode 100644,000000..100644
--- /dev/null
@@@ -1,110 -1,0 +1,116 @@@
-                 'addOns' => $this->config['addOns']
 +<?php
 +/**
 + * Gaslight Media Members Database
 + * Admin Management Add-Ons
 + *
 + * PHP version 5.5
 + *
 + * @category glmWordPressPlugin
 + * @package  glmMembersDatabase
 + * @author   Chuck Scott <cscott@gaslightmedia.com>
 + * @license  http://www.gaslightmedia.com Gaslightmedia
 + * @version  1.0.43
 + */
 +
 +/*
 + * This class performs the work for the default action of the "Members" menu
 + * option, which is to display the members dashboard.
 + *
 + */
 +class GlmMembersAdmin_management_addons
 +{
 +
 +    /**
 +     * 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;
 +
 +    }
 +
 +    /*
 +     * 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)
 +    {
++        $addOns = array();
++
++        foreach ($this->config['addOns'] as $a) {
++            $addOns[$a['slug']] = $a;
++            $addOns[$a['slug']]['print_r'] = print_r($a,1);
++        }
 +
 +        // Return status, suggested view, and data to controller
 +        return array(
 +            'status' => true,
 +            'menuItemRedirect' => false,
 +            'modelRedirect' => false,
 +            'view' => 'admin/management/addons.html',
 +            'data' => array(
++                'addOns' => $addOns
 +            )
 +        );
 +
 +    }
 +
 +}
 +
 +?>
@@@ -835,13 -835,13 +835,13 @@@ class GlmMembersAdmin_management_impor
                          if ($val['active'] == 't') {
  
                              // Member is active, so set to active-moderated
--                            $access = $this->config['memb_access_numb']['Moderated'];
++                            $access = $this->config['access_numb']['Moderated'];
                              $numbMembersActive++;
  
                          } else {
  
                              // Member is not active, so set to no display no access
--                            $access = $this->config['memb_access_numb']['NotDisplayed'];
++                            $access = $this->config['access_numb']['NotDisplayed'];
                              $numbMembersInactive++;
  
                          }
@@@ -98,6 -98,6 +98,8 @@@ class GlmMembersAdmin_management_index 
       */
      public function modelAction ($actionData = false)
      {
++        $settingsUpdated = false;
++
          // General settings are always stored in a record with ID=1.
          $id = 1;
  
  
                  // Update the general settings
                  $generalSettings = $this->updateEntry(1);
++                if ($generalSettings['status']) {
++                    $settingsUpdated = true;
++                }
  
                  // Display admin message that the data has been updated
                  glmMembersAdmin::addNotice('General Settings for the '.GLM_MEMBERS_PLUGIN_NAME.' plugin have been updated.', 'AdminNotice');
          $templateData = array(
              'reason' => '',
              'genSettings' => $generalSettings,
--            'timezones' =>  DateTimeZone::listIdentifiers()
--//            'canEdit' => $canEdit
++            'timezones' =>  DateTimeZone::listIdentifiers(),
++            'settingsUpdated' => $settingsUpdated
          );
  
          // Return status, suggested view, and data to controller
@@@ -102,9 -102,9 +102,10 @@@ class GlmMembersAdmin_member_index exte
          $success = true;
          $haveMember = false;
          $memberData = false;
++        $memberName = false;
          $memberID = 0;
          $archived = false;
--        $updated = false;
++        $memberUpdated = false;
          $haveMemberInfo = false;
  
          // Check for required Member Types
          $memberTypesStats = $MemberTypes->getStats();
          $haveMemberTypes = ($memberTypesStats > 0);
  
++        // Check if there's a logged in user who is locked to their own entity
++        $lockedToMember = apply_filters('glm_members_locked_to_member_id', false);
++        if ($lockedToMember) {
++
++                $memberID = $lockedToMember;
++
          // Check if a redirecting model supplied the member ID
--        if (isset($actionData['memberID'])) {
++        } elseif (isset($actionData['memberID'])) {
  
              $memberID = $actionData['memberID'];
  
                      $memberID = $memberData['fieldData']['id'];
                      $haveMember = true;
  
-                     // Go directly to the member information entry page
-                     return array(
-                         'status' => true,
-                         'menuItemRedirect' => 'member',
-                         'modelRedirect' => 'memberInfo',
-                         'view' => 'admin/member/memberInfo.html',
-                         'data' => array(
-                             'member' => $memberID
-                         )
-                     );
+                     // Update the member slug then get member data again
+                     $this->updateSlug($memberID);
 -                    // Go directly to the member information entry page
 -                    return array(
 -                        'status' => true,
 -                        'menuItemRedirect' => 'member',
 -                        'modelRedirect' => 'memberInfo',
 -                        'view' => 'admin/member/memberInfo.html',
 -                        'data' => array(
 -                            'member' => $memberID
 -                        )
 -                    );
++                    // Now get the updated entry with the slug
++                    $memberData = $this->editEntry($memberID);
  
                  }
  
              // If update was successful then use editEntry() to setup for the edit again.
              if ($memberData['status']) {
  
+                 $slug = $this->updateSlug($memberID);
                  $memberData = $this->editEntry($memberID);
--                $updated = true;
++                $memberUpdated = true;
  
                  // Also update all member info records with any possible name change
                  $sql = "
          $showArchived = false;
          if ($haveMember) {
  
++            // Get member name for title
++            $memberName =  $memberData['fieldData']['name'];
++
              // Hide archived unless instructed otherwise
              $hideArchived = '';
              if (!isset($_REQUEST['showArchived']) || $_REQUEST['showArchived'] != 'true') {
  
          }
  
++
          // Compile template data
          $templateData = array(
              'haveMemberTypes' => $haveMemberTypes,
              'haveMember' => $haveMember,
              'memberID' => $memberID,
              'member' => $memberData,
++            'memberName' => $memberName,
              'haveInfoRecords' => $haveInfoRecords,
              'memberInfoRecords' => $memberInfoRecords,
              'noActive' => $noActive,
              'showArchived' => $showArchived,
              'haveMemberInfo' => $haveMemberInfo,
--            'updated' => $updated,
++            'memberUpdated' => $memberUpdated,
++            'statusTypeNumbers' => $this->config['status_numb'],
              'statusPending' => $this->config['status_numb']['Pending']
          );
  
@@@ -219,6 -219,6 +219,7 @@@ class GlmMembersAdmin_member_memberInf
      {
  
          $this->optionIncludeSelectListData = true;
++        $memberUpdated = false;
  
          // Check for action option - Should be one of the values in the "switch" statement below
          $option = false;
          $this->memberData = $Members->getEntry($this->memberID);
          $this->fields['logo']['i_prefix'] = 'memb_'.$this->memberID.'_';
          $this->haveMember = true;
++        $memberName = $this->memberData['name'];
  
          // If no member info record, assume that we need to create a new one
          if ($this->memberInfoID <= 0 && $option != 'addNew') {
                  // Update submitted amenities
                  $this->updateAmenities();
  
++                // Load Image data class
                  require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataImages.php');
                  $Images = new GlmDataImages($this->wpdb, $this->config);
  
                  if ($this->haveMemberInfo) {
  
                      // Update the member Info data
--
                      $this->memberInfo = $this->updateEntry($this->memberInfoID, 'id', true, true);
++                    if ($this->memberInfo['status']) {
++                        $memberUpdated = true;
++                    }
  
                      break;
++
                  } else {
  
                      if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) {
                      ;";
                      $this->wpdb->query($sql);
  
++                    $this->memberInfo = $this->editEntry($this->memberInfoID);
                  }
  
                  break;
  
          // Compile template data
          $templateData = array(
++            'haveMember' => $this->haveMember,
              'memberID' => $this->memberID,
              'member' => $this->memberData,
++            'memberName' => $memberName,
              'memberInfoID' => $this->memberInfoID,
              'memberInfo' => $this->memberInfo,
++            'memberUpdated' => $memberUpdated,
              'availableCategories' => $this->categories,
              'availableAmenities' => $this->amenities,
              'haveImageGallery' => $this->haveImageGallery,
              } // For each amityy being submitted
  
              // Update the selected amenities for this member information record, returns new list
--            $this->memberAmenities = $Amenities->updateAmenityRef($this->config['ref_type_numb']['MemberInfo'], $this->memberID, $selectedAmenities);
++            $this->memberAmenities = $Amenities->updateAmenityRef($this->config['ref_type_numb']['MemberInfo'], $this->memberInfoID, $selectedAmenities);
  
          // Otherwise if this is a submission and there's no categories submitted, make sure there's none stored
          } elseif (isset($_REQUEST['option']) && $_REQUEST['option'] == 'submit') {
--            $this->memberAmenities = $Amenities->updateAmenityRef($this->config['ref_type_numb']['MemberInfo'], $this->memberID);
++            $this->memberAmenities = $Amenities->updateAmenityRef($this->config['ref_type_numb']['MemberInfo'], $this->memberInfoID);
          }
  
      }
@@@ -106,25 -106,24 +106,18 @@@ class GlmMembersAdmin_members_list exte
          $where = ' true ';
          $filterPending = false;
          $filterArchived = false;
--        $filterName = false;
 +        $filterCat = false;
          $haveFilter = false;
  
--        if (isset($_REQUEST['filterName'])) {
--            $filterName = $_REQUEST['filterName'];
--            $where .= " AND T.name like '%$filterName%'";
--            $haveFilter = true;
--        }
--
          // Check if this is a request to show archived members
          if (isset($_REQUEST['filterArchived'])) {
--            $where .= " AND T.access = ".$this->config['memb_access_numb']['Archived'];
++            $where .= " AND T.access = ".$this->config['access_numb']['Archived'];
              $filterArchived = true;
              $haveFilter = true;
  
          // If not, don't show them
          } else {
--            $where .= " AND T.access != ".$this->config['memb_access_numb']['Archived'];
++            $where .= " AND T.access != ".$this->config['access_numb']['Archived'];
          }
  
          // Get a list of categories for filtering
              'filterArchived' => $filterArchived,
              'filterPending' => $filterPending,
              'filterCat' => $filterCat,
--            'filterName' => stripslashes($filterName)
  //            'canEdit' => $canEdit
          );
  
@@@ -246,9 -246,9 +246,9 @@@ class GlmMembersFront_members_detail ex
                   FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX."members
                  WHERE id = T.member
              ) IN (
--                 ".$this->config['memb_access_numb']['NoAccess'].",
--                 ".$this->config['memb_access_numb']['Moderated'].",
--                 ".$this->config['memb_access_numb']['Full']."
++                 ".$this->config['access_numb']['NoAccess'].",
++                 ".$this->config['access_numb']['Moderated'].",
++                 ".$this->config['access_numb']['Full']."
                   )
          ";
          $memberInfoID = $this->getActiveInfoForMember($id, $where);
@@@ -399,16 -399,16 +399,16 @@@ class GlmMembersFront_members_list exte
              } // If an amenity search has been selected
          } // it doing amenity search
  
--        // Only look at active member information where the member is displayable  (memb_access = 20, 30, 40)
++        // Only look at active member information where the member is displayable  (access = 20, 30, 40)
          $where .= $whereSep."
              (
                  SELECT access
                   FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX."members
                  WHERE id = T.member
              ) IN (
--                 ".$this->config['memb_access_numb']['NoAccess'].",
--                 ".$this->config['memb_access_numb']['Moderated'].",
--                 ".$this->config['memb_access_numb']['Full']."
++                 ".$this->config['access_numb']['NoAccess'].",
++                 ".$this->config['access_numb']['Moderated'].",
++                 ".$this->config['access_numb']['Full']."
                   )
              AND T.status = ".$this->config['status_numb']['Active'];
  
@@@ -1,59 -1,59 +1,92 @@@
      <table class="glm-admin-table">
      
--{if $membersList}
++{if apply_filters('glm_members_permit_admin_widget_members', true)}    
++  {if $membersList}
          <tr>
              <td colspan="2">
--                <input  id="glmMembersList" type="text" id="autoTest" class="glm-right">
++                <input  id="glmMembersSearch" type="text" id="autoTest" class="glm-right">
                  <span class="glm-left">Member Search:</span>
              </td>
          </tr>
++        <script type="text/javascript">
++            jQuery(document).ready(function($) {
++                
++                /*
++                 * Do autocomplete search for member
++                 * label: What will be searched
++                 * value: What will be displayed when selected
++                 * id: Member id added so we can go to the member while showing what was selected
++                 * Also note that autocomplete does not properly render HTML codes, so we 
++                 * "unescape" them for HTML in Smarty.
++                 */
++                var availableTags = [
++        {foreach $membersList as $m}
++                    { label: "{$m.name|unescape:'html'}", value: "{$m.name|unescape:'html'}", id: '{$m.id}' },
++        {/foreach}
++                 ];
++                 $( "#glmMembersSearch" ).autocomplete({
++                     source: availableTags,
++                     html: true,
++                     select: function( event, ui ) {
++                         var memberID = ui.item.id;
++                         window.location.replace("{$adminURL}?page=glm-members-admin-menu-member&glm_action=index&member=" + memberID );
++                     }
++                 });
++                                 
++            });
++                
++        </script>
++  {/if}
++
  {/if}
--{if !$haveMemberTypes}
++
++{if apply_filters('glm_members_permit_admin_widget_warnings', true)}    
++  {if !$haveMemberTypes}
          <tr>
              <th class="glm-error">No Member Types</th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=memberTypes" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if !$haveCategories}
++  {/if}                
++  {if !$haveCategories}
          <tr>
              <th><span class="glm-error">No Member Categories</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=categories" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if !$haveAccommodationTypes}
++  {/if}                
++  {if !$haveAccommodationTypes}
          <tr>
              <th><span class="glm-error">No Accommodation Types</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=accommodationTypes" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if !$haveAmenities}
++  {/if}                
++  {if !$haveAmenities}
          <tr>
              <th><span class="glm-error">No Amenities</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=amenities" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if !$haveCities}
++  {/if}                
++  {if !$haveCities}
          <tr>
              <th><span class="glm-error">No Cities</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=cities" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if !$haveRegions}
++  {/if}                
++  {if !$haveRegions}
          <tr>
              <th><span class="glm-error">No Regions</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-configure&glm_action=regions" class="glm-right">Add</a></td>
          </tr>
--{/if}                
--{if $numbMembers == 0}
++  {/if}                
++  {if $numbMembers == 0}
          <tr>
             <th> <span class="glm-error">No Members</span></th>
              <td><a href="{$adminURL}?page=glm-members-admin-menu-member&glm_action=index&member_id=" class="glm-right">Add a Member</a></td>
          </tr>
--{/if}                
++  {/if}                
          <tr><th>Number of Members Listed: </th><td><a href="{$adminURL}?page=glm-members-admin-menu-members-list" class="glm-right">List Members</a><span class="glm-left">{$numbMembers}</span></td></tr>
      </table>
--    
--{if $haveBadLatLon}
++
++  {if $haveBadLatLon}
      <hr>
      <h4><span  class="glm-error">Records with Bad Map Locations</span></h4>
      
      {/foreach}
          </tbody>
      </table>
++  {/if}
  {/if}
  
--{if $membersPending}
++{if apply_filters('glm_members_permit_admin_widget_pending_info', true)}    
++  {if $membersPending}
      <hr>
      <h4><span  class="glm-error">Pending Member Information</span></h4>
      
--    <table class="wp-list-table widefat fixed posts glm-admin-table"">
++    <table class="wp-list-table widefat fixed posts glm-admin-table">
          <tbody>
      {assign var="i" value="0"}
      {foreach $pendingList as $p}
              <tr class="alternate">
          {/if}
                  <td>
--                    <a href="{$adminURL}?page=glm-members-admin-menu-member&glm_action=memberInfo&member={$p.member_pointer}&id={$p.id}}">{$p.member}</a>
++                    <span class="glm-admin-table-medium-text">
++                        <a href="{$adminURL}?page=glm-members-admin-menu-member&glm_action=memberInfo&member={$p.member_pointer}&id={$p.id}}">{$p.member}</a>:  
++                        {$p.reference_name}
++                    </span>
                  </td>
              </tr>
      {/foreach}
          </tbody>
      </table>
++  {/if}
  {/if}
  
--{if $membersList}
--    <script type="text/javascript">
--        jQuery(document).ready(function($) {
--            
--              /*
--               * Do autocomplete search for member
--               * label: What will be searched
--               * value: What will be displayed when selected
--               * id: Member id added so we can go to the member while showing what was selected
--               * Also note that autocomplete does not properly render HTML codes, so we 
--               * "unescape" them for HTML in Smarty.
--               */
--              var availableTags = [
--    {foreach $membersList as $m}
--                  { label: "{$m.name|unescape:'html'}", value: "{$m.name|unescape:'html'}", id: '{$m.id}' },
--    {/foreach}
--             ];
--             $( "#glmMembersList" ).autocomplete({
--                 source: availableTags,
--                 html: true,
--                 select: function( event, ui ) {
--                       var memberID = ui.item.id;
--                       window.location.replace("{$adminURL}?page=glm-members-admin-menu-member&glm_action=index&member=" + memberID );
--                 }
--             });
--                             
--        });
--            
--    </script>
--{/if}
++  
index 4deb4bf,0000000..76dcda7
mode 100644,000000..100644
--- /dev/null
@@@ -1,25 -1,0 +1,17 @@@
-     <table class="wp-list-table widefat fixed posts glm-admin-table"">
-         <tbody>
-     {assign var="i" value="0"}
 +{include file='admin/management/header.html'}
 +
 +    <h2>Currently Installed and Active GLM Members DB Add-Ons</h2>
 +    
 +{if $addOns}
 +    
-         {if $i++ is odd by 1} 
-             <tr>
-         {else}
-             <tr class="alternate">
-         {/if}
-                 <td>
-                     {$a.name}
-                 </td>
-             </tr>
++    <ul class="glm-li">
 +    {foreach $addOns as $a}
-         </tbody>
-     </table>
++        <li>
++            {$a.name}<br>
++            <pre>{$a.print_r}</pre>
++        </li>
 +    {/foreach}
++    </ul>
 +{/if}
 +        
 +{include file='admin/footer.html'}
index 15a4eb8,0000000..39b5867
mode 100644,000000..100644
--- /dev/null
@@@ -1,152 -1,0 +1,368 @@@
-             <td width="70%">
 +{include file='admin/management/header.html'}
 +
 +   <h2>Hooks Into GLM Member DB Reference</h2>
 +    
 +    <p>
 +        Listed below are hooks into the GLM Member DB plugin. These hooks are used by
 +        add-ons (child plugins) and by themes to extend and modify behavior and output 
 +        content of this plugin and its addons.   
 +    </p>
 +    
 +    <table class="glm-admin-table">
 +        <tr><th>Hook</th><th>Type</th><th>Description</th></tr>
 +                <tr>
 +            <th>glm-member-db-register-addon</th>
 +            <td>Filter</td>
-                 <p>
++            <td>
 +                Informs the GLM Meembers DB plugin of an installed add-on plugin. Information
 +                on the plugin is provided in an array that's returned from the function 
 +                referenced in the add_filer() call.
-             <td width="70%">
++                <p>f
 +                The data compiled from all registered add-on plugins is stored in the $config
 +                object for reference throughout this plugin.
 +                </p><p>
 +                An example from the registration of
 +                the Contacts add-on is below.
 +                </p>
 +                <div class="glm-code">
 +function glmMembersRegisterContacts($addOns) {
 +    $addOns[GLM_MEMBERS_CONTACTS_PLUGIN_SLUG] =  array(
 +            'dir' => GLM_MEMBERS_CONTACTS_PLUGIN_PATH,
 +            'name' =>  GLM_MEMBERS_CONTACTS_PLUGIN_NAME,
 +            'short_name' => GLM_MEMBERS_CONTACTS_PLUGIN_SHORT_NAME
 +    );
 +    return $addOns;
 +}
 +add_filter('glm-member-db-register-addon','glmMembersRegisterContacts', 10, 1);
 +                </div>
 +            </td>
 +        </tr>
 +        <tr>
 +            <th>glm-member-db-add-menu</th>
 +            <td>Action</td>
-                         <tr><th>Add Member</th><td>Sub-Menu</td><td>glm-members-admin-menu-member</td></tr>
++            <td>
 +                Hook to add a menu or menus (or sub-menus) to the GLM Member DB menus. Note that
 +                you may have only menu items and sub-menu items under a main menu item, or in other 
 +                words, only 3 levels of menus.
 +                <div class="glm-code">
 +// This call will generally be in the constructor of the admin controller in the add-on plugin                
 +add_action('glm-member-db-add-menu', array($this, 'glmMembersAddMenusContacts'));
 +
 +// The following two functions would be located elsewhere of the admin controller class.
 +public function glmMembersAddMenusContacts()
 +{
 +    // Add hooks to WordPress
 +    add_action('admin_menu', array($this, 'configureMenus'));
 +}
 +public function configureMenus ()
 +{
 +    // A test menu
 +    add_submenu_page(
 +        'glm-members-admin-menu-members',
 +        'Contacts',
 +        'Contacts',
 +        'glm_members_edit',
 +        'glm-members-admin-menu-contacts',
 +        array($this, 'glmMembersAdminMenuContacts')
 +    );
 +}
 +                </div>
 +                <p>
 +                Note that in the example above that the function references are as they as 
 +                would be used when contained in a class and being called from another
 +                method--such as '_constructor()'. This will likely be the case since the
 +                add_action() call will generally be located in the constructor of the 
 +                add-on's admin controller and the the function called by that will be
 +                a function in the same class.  
 +                </p>
 +                <p>
 +                Current list of standard GLM Member DB menu items.
 +                </p>
 +                <table class="glm-admin-table" border=1">
 +                    <thead>
 +                        <tr ><th>Menu</th><th>level</th><th>Slug</th></tr>
 +                    </thead>
 +                    <tbody>
 +                        <tr><th>Member DB</th><td>Main Menu</td><td>glm-members-admin-menu-members</td></tr>
 +                        <tr><th>Members</th><td>Sub-Menu</td><td>(same as Member DB main menu item)</td></tr>
 +                        <tr><th>Members</th><td>Sub-Menu</td><td>glm-members-admin-menu-members</td></tr>
 +                        <tr><th>Member List</th><td>Sub-Sub-Menu</td><td>glm-members-admin-menu-members-list</td></tr>
-             <td width="70%">
++                        <tr><th>Member</th><td>Sub-Menu</td><td>glm-members-admin-menu-member</td></tr>
 +                        <tr><th>Configure</th><td>Sub-Menu</td><td>glm-members-admin-menu-configure</td></tr>
 +                        <tr><th>Management</th><td>Sub-Menu</td><td>glm-members-admin-menu-management</td></tr>
 +                        <tr><th>Shortcodes</th><td>Sub-Menu</td><td>glm-members-admin-menu-shortcodes</td></tr>
 +                    </tbody>
 +                </table>
 +            </td>
 +        </tr>
 +        <tr>
 +            <th>glm-member-db-add-tab-for-{literal}{menu_item}{/literal}</th>
 +            <td>Filter</td>
-         
++            <td>
 +                Hook to add a tab or tabs to the header for pages in a particular page where
 +                {literal}{menu_item}{/literal} should be the name of the menu item (page) where 
 +                the tab(s) should be added.
 +                <p>
 +                As shown in the example below, the $addOnTabs array that is passed is an array
 +                of tab definition arrays wherein 'text' is the text displayed on the tab and 
 +                'action' is the action that is to be performed when the tab is clicked. 
 +                </p>
 +                <div class="glm-code">
 +// This call will generally be in the constructor of the admin controller in the add-on plugin                
 +add_filter('glm-member-db-add-tab-for-members', array($this, 'glmMembersAddTabForMembers'));
 +
 +// The following two functions would be located elsewhere in the admin controller class.
 +public function glmMembersAddTabForMembers($addOnTabs)
 +{
 +    $newTabs = array(
 +        array(
 +            'text' => 'New Tab',
 +            'action' => 'contact'
 +        ),
 +        array(
 +            'text' => 'Another Tab',
 +            'action' => 'anotherAction'
 +        )
 +    );
 +    $addOnTabs = array_merge($addOnTabs, $newTabs);
 +    return $addOnTabs;
 +}
 +                </div>
 +                <p>
 +                The tabs are generated from this array by the related header.html template 
 +                for the related menu item.
 +                </p>
 +                <p>
 +                Note that in the example above that the function references are as they as 
 +                would be used when contained in a class and being called from another
 +                method--such as '_constructor()'. This will likely be the case since the
 +                add_filter() call will generally be located in the constructor of the 
 +                add-on's admin controller and the the function called by that will be
 +                a function in the same class.  
 +                </p>
 +            </td>
 +        </tr>
++        <tr>
++            <th>glm_members_current_logged_in_user</th>
++            <td>Filter</td>
++            <td>
++                Hook requesting additional information on any currently logged in user.
++                <p>
++                This hook is used to accumulate current user information before a controller
++                is executed. The current user information is stored in $config as 'loggedInUser'
++                so as to be available to all subsequent code. The data is stored as an array 
++                and defaults to having one 'wpUser' sub-array.  
++                </p>
++                <p>
++                The code providing the data should return the supplied data even if it is not
++                contributing any additional user information.  
++                </p>
++                <p>
++                If the code is adding user information (i.e. the Contacts add-on adding information
++                on a "contact" user), it should probably supply the data in a separate sub-array
++                (i.e. 'contactUser'). In any case, it must still return the wpUser sub-array
++                data that was provided by the hook.
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_locked_to_member_id</th>
++            <td>Filter</td>
++            <td>
++                Hook requesting any member ID to which the current user might be restricted.
++                <p>
++                The code providing the data should return the provided value if it has no member ID
++                it wishes to pass back, thus permitting this hook to be chained to more than one 
++                possible source of a member ID to which the user should be restricted. For example,
++                a user might only have permissions to view or edit one member and therefore should
++                not have access to any others.
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_menu_members</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the "Members" menu. 
++                <p>
++                This hook passes the hooked code a boolean saying whether the permission has 
++                been withdrawn by previously hooked code. The default is true, so all hooked
++                code must pass true back to the hook for the permission to be granted.  
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_menu_member</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the "Member" menu. 
++                <p>
++                This hook passes the hooked code a boolean saying whether the permission has 
++                been withdrawn by previously hooked code. The default is true, so all hooked
++                code must pass true back to the hook for the permission to be granted.  
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_menu_configure</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the "Configure" menu. 
++                <p>
++                This hook passes the hooked code a boolean saying whether the permission has 
++                been withdrawn by previously hooked code. The default is true, so all hooked
++                code must pass true back to the hook for the permission to be granted.  
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_menu_management</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the "Management" menu. 
++                <p>
++                This hook passes the hooked code a boolean saying whether the permission has 
++                been withdrawn by previously hooked code. The default is true, so all hooked
++                code must pass true back to the hook for the permission to be granted.  
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_menu_menu_shortcodes</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the "Shortcodes" menu. 
++                <p>
++                This hook passes the hooked code a boolean saying whether the permission has 
++                been withdrawn by previously hooked code. The default is true, so all hooked
++                code must pass true back to the hook for the permission to be granted.  
++                </p>
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_members_index_add_member</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to add a new member on the 
++                Members index page. 
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_members_index_member_config_warning</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to show the user notices regarding
++                information managed under the "Configure" menu. 
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_index_edit_member</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to edit member base data.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_index_add_member_info_version</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to add a new member information 
++                version on the Member index page.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_index_view_member_info_version</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to view member infor versions.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_index_clone_activate_info_version</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to Clone or Activate member 
++                information versions on the Member index page.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_contacts_tab</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see the member Contacts tab.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_contacts_add_contact</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to add a new contact.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_contacts_view_contact</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to view a contact.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_contacts_edit_contact</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to edit a contact.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_widget_members</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to search members in the Dashboard Widget.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_widget_warnings</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see configuration and other members 
++                warnings in the Dashboard Widget.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_widget_pending_info</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see a list of pending information
++                records for all members in the Dashboard Widget.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_index_list_inactive_info</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to see a list of inactive member information.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_member_info_edit</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to edit member information.
++            </td>
++        </tr>
++        <tr>
++            <th>glm_members_permit_admin_profile_index_edit_profile</th>
++            <td>Filter</td>
++            <td>
++                Hook to test if the logged in user is permitted to edit their own profile.
++            </td>
++        </tr>
 +    </table>
 +        
++        
++        
 +{include file='admin/footer.html'}
 +
 +
 +
 +'glm-member-db-add-tab-for-'.$menuItem,
@@@ -1,5 -1,5 +1,8 @@@
  {include file='admin/management/header.html'}
      
++    
++    {if $settingsUpdated}<h2 class="glm-notice glm-flash-updated">Settings Updated</h2>{/if}
++    
      <form action="{$thisURL}?page={$thisPage}" method="post" enctype="multipart/form-data">
          <input type="hidden" name="glm_action" value="index">
          <input type="hidden" name="option" value="submit">
          </table>
          <input type="submit" value="Update Settings" class="button-primary">
      </form>
++    
++    <script type="text/javascript">
++        
++        jQuery(document).ready(function($) {
++
++            // Flash certain elements for a short time after display      
++            $(".glm-flash-updated").fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500);
++                    
++        });
++    </script>
++
  {include file='admin/footer.html'}
@@@ -1,31 -1,16 +1,39 @@@
-   {assign var="memberInfoID" value="false"}
 +{* Sometimes this header is called without a memberInfoID. It's easier to handle it here that to set this in all models that don't need it. *}
 +{if !isset($memberInfoID)}
-   {assign var="memberInfo" value="false"}
++  {assign var="memberInfoID" value=false}
 +{/if}
 +{if !isset($memberInfo)}
++  {assign var="memberInfo" value=false}
 +{/if}
 +
  <div class="wrap">
         
--    <h2>Member Data</h2>
--    
++    <h2>
++        {if $haveMember}
++            Member: <span class="glm-notice">{$memberName}</span>
++        {else}
++            New Member
++        {/if}
++    </h2>
++
      <h2 class="nav-tab-wrapper">
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=index&member={$memberID}" class="nav-tab{if $thisAction==index}-active{/if}">Member Dashboard</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&id={$memberInfoID}" class="nav-tab{if $thisAction==memberInfo}-active{/if} {if !$member || !$memberInfo}disabled{/if}">Member Info</a>
 -<!-- 
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=locations&member={$memberID}" class="nav-tab{if $thisAction==locations}-active{/if} {if !$member || !$memberInfo}disabled{/if}">Locations</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=facilities&member={$memberID}" class="nav-tab{if $thisAction==facilities}-active{/if} {if !$member || !$memberInfo}disabled{/if}">Facilities</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=attractions&member={$memberID}" class="nav-tab{if $thisAction==attractions}-active{/if} {if !$member || !$memberInfo}disabled{/if}">Attractions</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=contacts&member={$memberID}" class="nav-tab{if $thisAction==contacts}-active{/if} {if !$member || !$memberInfo}disabled{/if}">Contacts</a>
 --->        
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=index&member={$memberID}&id={$memberInfoID}" class="nav-tab{if $thisAction==index}-active{/if}">Member Dashboard</a>
- {if $memberInfoID || $thisAction == 'memberInfo'}        
++{if $memberID}
++  {if $memberInfoID}
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&memberInfo={$memberInfoID}" class="nav-tab{if $thisAction==memberInfo}-active{/if} {if !$memberID || !$memberInfoID}disabled{/if}">Member Info</a>
- {/if}        
- {foreach $addOnTabs as $a}
++  {/if}
++  {foreach $addOnTabs as $a}
 +        <a href="{$thisURL}?page={$thisPage}&glm_action={$a.action}&member={$memberID}&memberInfo={$memberInfoID}" class="nav-tab{if $thisAction==$a.action}-active{/if}">{$a.text}</a>
- {/foreach}        
++  {/foreach}        
++{/if}
 +
 +{* Not needed yet 
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=locations&member={$memberID}" class="nav-tab{if $thisAction==locations}-active{/if} {if !$memberID || !$memberInfo}disabled{/if}">Locations</a>
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=facilities&member={$memberID}" class="nav-tab{if $thisAction==facilities}-active{/if} {if !$memberID || !$memberInfo}disabled{/if}">Facilities</a>
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=attractions&member={$memberID}" class="nav-tab{if $thisAction==attractions}-active{/if} {if !$memberID || !$memberInfo}disabled{/if}">Attractions</a>
 +        <a href="{$thisURL}?page={$thisPage}&glm_action=contacts&member={$memberID}" class="nav-tab{if $thisAction==contacts}-active{/if} {if !$memberID || !$memberInfo}disabled{/if}">Contacts</a>
 +*}
 +        
      </h2>
      <div id="glm-admin-content-container">
      
@@@ -2,18 -2,18 +2,19 @@@
  
  {if $haveMemberTypes}
  
--  {if $updated}
--    <h3 class="glm-notice glm-right">Record Updated</h3>
--  {/if}
  
      <h2>
    {if $haveMember}
--        {$member.fieldData.name}
++        General Member Information
    {else}
          Add New Member
    {/if}
      </h2>
++  {if $memberUpdated}
++    <h2 class="glm-notice glm-flash-updated">Member Updated</h2>
++  {/if}
    
++  {if apply_filters('glm_members_permit_admin_member_index_edit_member', true)}
      <form action="{$thisURL}?page={$thisPage}" method="post" enctype="multipart/form-data">
          <input type="hidden" name="glm_action" value="index">
        {if $haveMember}
@@@ -26,7 -26,7 +27,6 @@@
        {/if}
          
          <table class="glm-admin-table">
--            {if $haveMember}<tr><th>ID</th><td>{$member.fieldData.id}</td></tr>{/if}
              <tr>
                  <th {if $member.fieldRequired.name}class="glm-required"{/if}>Member Name:</th>
                  <td {if $member.fieldFail.name}class="glm-form-bad-input"{/if}>
              
          </table>
          <p><span class="glm-required">*</span> Required</p>
--  {if $haveMember}
++    {if $haveMember}
          <input type="submit" value="Update member">
--  {else}
++    {else}
          <input type="submit" value="Add new member">
--  {/if}
++    {/if}
      </form>
++  {else}
++    {if $haveMember}
++        <table class="glm-admin-table">
++            <tr>
++                <th>Member Name:</th>
++                <td>{$member.fieldData.name}</td>
++            </tr>
++            <tr>
++                <th>Name for URLs:</th>
++                <td>{$member.fieldData.member_slug}</td>
++            </tr>
++            <tr>
++                <th>Member Display & Access:</th>
++                <td>{$member.fieldData.access.name}</td>
++            </tr>
++            <tr>
++                <th>Member Type:</th>
++                <td>{$member.fieldData.member_type.name}</td>
++            </tr>            
++            <tr><th>Date created:</th><td>{$member.fieldData.created.date}</td></tr>            
++        </table>
++    {else}
++        <h3>No member information available.</h3>
++    {/if}
++  {/if}
      
    <p>&nbsp;</p>
  
++  {if $haveMember}
++
++  {if apply_filters('glm_members_permit_admin_member_index_view_member_info_version', true)}
++    {if apply_filters('glm_members_permit_admin_member_index_add_member_info_version', true)}
      <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}" class="button-primary glm-button glm-right">Add New Member Information Version</a>
++    {/if}   
      <br clear="all">
      <p>
          <h3 class="glm-left">Member Information Versions</h3>
          </span>
      </p> 
  
-   {if $haveMember}
--    <table class="wp-list-table widefat fixed posts glm-admin-table"">
++    <table class="wp-list-table striped glm-admin-table">
          <thead>
              <tr>
                  <th>Access</th>
              </tr>
          </thead>
          <tbody>
--    
 -  {if $haveMember}
--    {if $haveInfoRecords}
--    
--      {assign var="i" value="0"}
--      {foreach $memberInfoRecords as $m}
--        {if $i++ is odd by 1} 
++        
++      {if $haveInfoRecords}
++        {assign var="i" value="0"}
++        {foreach $memberInfoRecords as $m}
++        
++         {if $m.status.value == $statusTypeNumbers.Active || apply_filters('glm_members_permit_admin_member_index_list_inactive_info', true)}
++          {if $i++ is odd by 1} 
              <tr>
--        {else}
++          {else}
              <tr class="alternate{if $m.status.name == 'Active'} glm-admin-table-active{/if}">
--        {/if}
-                 <td><a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&memberInfo={$m.id}"{if $m.status.value == $statusPending} class="glm-notice"{/if}>{$m.status.name}</a></td>
 -                <td><a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&id={$m.id}"{if $m.status.value == $statusPending} class="glm-notice"{/if}>{$m.status.name}</a></td>
++          {/if}
++                <td>
++                    <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&memberInfo={$m.id}"{if $m.status.value == $statusPending} class="glm-notice"{/if}>{$m.status.name}</a>
++                </td>
                  <td>{$m.reference_name}</td>
                  <td>{$m.create_time.datetime}</td>
                  <td>{$m.modify_time.datetime}</td>
                  <td>
 -                    <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&id={$m.id}&option=clone" class="button-primary glm-right">Clone</a>&nbsp;
++          {if apply_filters('glm_members_permit_admin_member_index_clone_activate_info_version', true)}       
 +                    <a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}&memberInfo={$m.id}&option=clone" class="button-primary glm-right">Clone</a>&nbsp;
                      {if $m.status.name != 'Active'}<a href="{$thisURL}?page={$thisPage}&glm_action=index&member={$memberID}&activateID={$m.id}" class="button-primary glm-button glm-right">Activate</a>{/if}
++          {/if}
                  </td>
              </tr>
--      {/foreach}
--    {else}
--    <tr><td colspan="5"><a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}">Click here too start entering information for this member.</a></td></tr>
--  {/if}
++            
++            
++         {/if}
++        {/foreach}
++      {else} <!-- haveInfoRecords -->
++            <tr><td colspan="5"><a href="{$thisURL}?page={$thisPage}&glm_action=memberInfo&member={$memberID}">Click here too start entering information for this member.</a></td></tr>
++      {/if}
          </tbody>
      </table>
++   {/if} <!-- apply_filters -->
   {/if}
  
  {else}        
                  window.location.replace("{$thisURL}?page={$thisPage}&glm_action=index&member={$memberID}&showArchived=" + checked);               
                });
                
++            // Flash certain elements for a short time after display      
++            $(".glm-flash-updated").fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500);
++
          });
      </script>
  
@@@ -1,10 -1,10 +1,15 @@@
  {include file='admin/member/header.html'}
  
      <script src="http://maps.googleapis.com/maps/api/js?sensor=true&key={$settings.google_maps_api_key}"></script>
++    <script type="text/javascript">var enableDragable = true;</script>
++
++    {if $memberUpdated}<h2 class="glm-notice glm-flash-updated">Member Information Updated</h2>{/if}
      
      <!--[if lt IE 9]>
        <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
      <![endif]-->
++
++{if apply_filters('glm_members_permit_admin_member_info_edit', true)}
      
      {if $memberInfoID && $memberInfo}
          <!--  Delete Member Information dialog -->
                  "Show Archiived Versions" checkbox at the top right of the versions list on that page to include archived versions.
              </p>
  
--      {/if}
++      {/if} <!-- status == 10 -->
          </div>
  
          <h2>Edit Member Information</h2>
      {else}
          <h2>Add New Member Information</h2>
--    {/if}
++    {/if} <!-- memberInfoID && memberInfo -->
  
      <form action="{$thisURL}?page={$thisPage}" method="post" enctype="multipart/form-data">
          <input type="hidden" name="glm_action" value="memberInfo">
                  <th>Access:</th>
                  <td>{$member.access.name}</td>
              </tr>                        
--       {/if}            
--    {if $noActive}
++      {/if}            
++      {if $noActive}
              <tr><td colspan="2"><h3 class="glm-error">You do not have any active information for this member.</h3></td></tr>
--    {/if}
--            <tr><td colspan="2">&nbsp;</td></tr>
--            <tr>
++      {/if}
        {if $memberInfoID && $memberInfo}
              <tr>
                  <th>Created:</th>
              </tr>            
              <tr>
                  <th>Last Updated:</th>
--                <td>{if isset($create_time)}{$memberInfo.fieldData.modify_time.datetime}{/if}</td>
++                <td>{$memberInfo.fieldData.modify_time.datetime}</td>
              </tr>
        {/if}
++            
              <th>Member Info Status:</th>
                  <td>
                      <select name="status">
                      {if $memberInfo.fieldFail.status}<p>{$memberInfo.fieldFail.status}</p>{/if}
                  </td>
              </tr>
--            <tr>
--                <td>&nbsp;</td>
--                <td>
--                    <h3>Descriptions</h3>
--                </td>
--            </tr>
              <tr>
                  <th {if $memberInfo.fieldRequired.reference_name}class="glm-required"{/if}>Reference Name:</th>
                  <td {if $memberInfo.fieldFail.reference_name}class="glm-form-bad-input"{/if}>
                      {if $memberInfo.fieldFail.reference_name}<p>{$memberInfo.fieldFail.reference_name}</p>{/if}
                  </td>
              </tr>
++            <tr>
++                <td>&nbsp;</td>
++                <td>
++                    <h3>Descriptions</h3>
++                </td>
++            </tr>
              <tr>
                  <th {if $memberInfo.fieldRequired.descr}class="glm-required"{/if}>Description:</th>
                  <td {if $memberInfo.fieldFail.descr}class="glm-form-bad-input"{/if}>
                          Use + and - buttons or the mouse wheel to zoom in or out.
                          Click and drag anywhere else on the map to move to another area.
                      </p>
--                    <div id="locationMap" class="glm-map-edit">(map loads here)</div>     
++                    <div id="locationMap" class="glm-map-edit">(map loads here)</div>
                      Selected Position: <span id="mapPosition">Lat {$memberInfo.fieldData.lat}, Lon {$memberInfo.fieldData.lon}</span>
                  </td>
              </tr>
              <tr>
                  <th {if $memberInfo.fieldRequired.logo}class="glm-required"{/if}>Logo:</th>
                  <td {if $memberInfo.fieldFail.logo}class="glm-form-bad-input"{/if}>
--        {if $memberInfo.fieldData.logo}
--
--                    <!--  Add new category dialog -->
--                    <div id="largeLogoDialog" class="glm-dialog-box" title="Large sized image">
--                        <img src="{$glmPluginMediaURL}/images/large/{$memberInfo.fieldData.logo}">
--                        <a id="largeLogoCancel" class="button-primary glm-right">Close</a><br>
--                    </div>
--
                      <table class="glm-admin-image-edit-table">
++        {if $memberInfo.fieldData.logo}
                          <tr>
--                            <td><img src="{$glmPluginMediaURL}/images/small/{$memberInfo.fieldData.logo}"></td> 
++                            <td>
++                                <div class="glm-galleryImage" data-id="logo">
++                                    <img src="{$glmPluginMediaURL}/images/small/{$memberInfo.fieldData.logo}">
++                                </div>
++                            </td>
                              <td>
                                  <input type="checkbox" name="logo_delete"> Delete Image<br>
                                  {$memberInfo.fieldData.logo}<br>
--                                <p><div id="largeLogoButton" class="button-primary">Show Large Logo Image</div></p>
                              </td>
--                    
                          </tr>
--                    </table>
          {/if}
--                    <input type="file" name="logo_new">
++                        <tr><td colspan="2"><b>New image:</b> <input type="file" name="logo_new"></td></tr>
++                    </table>
++                    <div id="glm-galleryImageLarger_logo" class="glm-imageDialog"><img src="{$glmPluginMediaURL}/images/large/{$memberInfo.fieldData.logo}"></div>
                      {if $memberInfo.fieldFail.logo}<p>{$memberInfo.fieldFail.logo}</p>{/if}
                  </td>
              </tr>
                                              <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>
++                                                <td rowspan="2">
++                                                    <table>
++                                                        <tr><th>Delete:</th><td><input type="checkbox" name="galleryImage_delete[{ id }]" disabled></td></tr>
++                                                        <tr><th>Selected Image:</th><td><input type="radio" name="galleryImage_selected" value="{ id }"></td></tr>
++                                                        <tr><th>Featured Image:</th><td><input type="checkbox" name="galleryImage_featured[{ id }]"></td></tr>
++                                                        <tr><th colspan="2" class="glm-notice" style="font-size: 1.2em;">New Upload</th></tr>
++                                                    </table>                             
++                                                </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-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>
++                    <div class="glm-right"><b>No Selected Image:</b> <input type="radio" name="galleryImage_selected" value="0"><br>&nbsp;</div>
                      <ul class="glm-galleryImages">
                          <!-- Note that id in li is needed for sorting -->
          {if $haveImageGallery}     
                                      <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>
++                                        <td rowspan="2">
++                                            <table>
++                                                <tr><th>Delete:</th><td><input type="checkbox" name="galleryImage_delete[{$i.id}]"></td></tr>
++                                                <tr><th>Selected Image:</th><td><input type="radio" name="galleryImage_selected" value="{$i.id}" {if $i.selected.value}checked="checked"{/if}></td></tr>
++                                                <tr><th>Featured Image:</th><td><input type="checkbox" name="galleryImage_featured[{$i.id}]" {if $i.featured.value}checked="checked"{/if}></td></tr>
++                                            </table>                             
++                                            <input type="hidden" name="galleryImage_position[{$i.id}]" value="{$i.position}">
++                                        </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>
              </tr>
          </table>
          <p><span class="glm-required">*</span> Required</p>
--        <input type="submit" name="Add new member">
--        
++        <input type="submit" value="{if $memberInfoID && $memberInfo}Update member information{else}Add new member information{/if}">
++
      </form>
++    
++{else} <!-- No - glm_members_permit_admin_member_info_edit -->
++        <script type="text/javascript">var enableDragable = false;</script>
++
++        <table class="glm-admin-table">
++            
++            <tr><th>Member Name:</th><td>{$member.name}</td></tr>
++            <tr><th>Member Type:</th><td>{$member.member_type.name}</td></tr>            
++            <tr><th>Access:</th><td>{$member.access.name}</td></tr>                        
++            <tr><th>Created:</th><td>{$memberInfo.fieldData.create_time.datetime}</td></tr>            
++            <tr><th>Last Updated:</th><td>{$memberInfo.fieldData.modify_time.datetime}</td></tr>
++            <tr><th>Member Info Status:</th><td>{$memberInfo.fieldData.status.name}</option></td></tr>
++            <tr><th>Reference Name:</th><td>{$memberInfo.fieldData.reference_name}</td></tr>
++            <tr>
++                <td>&nbsp;</td>
++                <td>
++                    <h3>Descriptions</h3>
++                </td>
++            </tr>
++            <tr><th>Description:</th><td>{$memberInfo.fieldData.descr|escape:quotes}</td></tr>
++            <tr><th>Short Description:</th><td>{$memberInfo.fieldData.short_descr}</td></tr>
++            <tr>
++                <td>&nbsp;</td>
++                <td>
++                    <h3>Member Address</h3>
++                    <p>The map below will display the likely location as you enter or edit the address.</p> 
++                </td>
++            </tr>
++            <tr>
++                <th>Address:</th>
++                <td>
++                    {$memberInfo.fieldData.addr1}<br>
++                    {if $memberInfo.fieldData.addr2 != ''}{$memberInfo.fieldData.addr2}<br>{/if}
++                    {$memberInfo.fieldData.city.name}, {$memberInfo.fieldData.state.name} {$memberInfo.fieldData.zip}<br>
++                    {$memberInfo.fieldData.country.name}
++                </td>
++            </tr>
++            <tr>
++                {if $memberInfo.fieldRequired.lat}<th class="emRequiredInputField">{else}<th>{/if}Location:</th>
++                <td>
++                    <input id="glmLat" name="lat" type="hidden" value="{$memberInfo.fieldData.lat}">
++                    <input id="glmLng" name="lon" type="hidden" value="{$memberInfo.fieldData.lon}">
++                    <div id="locationMap" class="glm-map-edit">(map loads here)</div>     
++                    Selected Position: <span id="mapPosition">Lat {$memberInfo.fieldData.lat}, Lon {$memberInfo.fieldData.lon}</span>
++                </td>
++            </tr>
++            <tr>
++                <td>&nbsp;</td>
++                <td>
++                    <h3>Other Information</h3>
++                </td>
++            </tr>
++            <tr>
++                <th>Categories</th>
++                <td class="glm-item-container">
++        {if isset($memberInfo.fieldData.categories) && $memberInfo.fieldData.categories}
++            {foreach from=$memberInfo.fieldData.categories item=c}
++                    <div data-id="{$c.id}" class="glm-dynSelect-item glm-members-catgegory"> 
++                        {if $c.parent_name != ''}{$c.parent_name}: {/if}{$c.name} 
++                        <input type="hidden" name="category[{$c.id}]" value="{$c.id}">
++                   </div>                    
++            {/foreach}
++        {/if}                    
++                </td>
++            </tr>
++            <tr>
++                <th>Amenities</th>
++                <td class="glm-item-container">
++                    <!-- Amenity Selection -->
++         {if isset($memberInfo.fieldData.amenities) && $memberInfo.fieldData.amenities}
++            {foreach from=$memberInfo.fieldData.amenities item=c}
++                    <div data-id="{$c.id}" class="glm-dynSelect-item glm-members-amenity"> 
++                        {$c.name} 
++                        <input type="hidden" name="amenity[{$c.id}]" value="{$c.id}">
++                   </div>                    
++        {/foreach}
++        {/if}                    
++                </td>
++            </tr>
++            <tr><th>Region:</th><td>{$memberInfo.fieldData.region.name}</td></tr>
++            <tr><th>Phone #:</th><td>{$memberInfo.fieldData.phone}</td></tr>
++            <tr><th>Toll Free #:</th><td>{$memberInfo.fieldData.toll_free}</td></tr>
++            <tr><th>Web Address (URL):</th><td><a href="{$memberInfo.fieldData.url}" target="urlTarget">{$memberInfo.fieldData.url}</a></td></tr>
++            <tr><th>E-Mail Address:</th><td>{$memberInfo.fieldData.email}</td></tr>
++            <tr><th>Logo:</th>
++                <td {if $memberInfo.fieldFail.logo}class="glm-form-bad-input"{/if}>
++        {if $memberInfo.fieldData.logo}
++                    <div class="glm-galleryImage" data-id="logo">
++                        <img src="{$glmPluginMediaURL}/images/small/{$memberInfo.fieldData.logo}">
++                    </div>
++                    <div id="glm-galleryImageLarger_logo" class="glm-imageDialog"><img src="{$glmPluginMediaURL}/images/large/{$memberInfo.fieldData.logo}"></div>
++        {/if}
++                </td>
++            </tr>
++            <tr>
++                <th>Credit Cards Accepted:</th>
++                <td>
++        {foreach from=$memberInfo.fieldData.cc_type.bitmap item=v}
++                    {$v.name}&nbsp;&nbsp;
++        {/foreach}                    
++                </td>
++            </tr>
++            <tr><th>Notes:</th><td>{$memberInfo.fieldData.notes}</td></tr>
++            <tr>
++                <th>Image Gallery</th>
++                <td class="glm-item-container glm-imageGalleryContainer">
++                    <ul class="glm-galleryImages">
++        {if $haveImageGallery}     
++            {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>
++                                   </tr>
++                                    <tr>
++                                        <th>Description:</th>
++                                        <td><textarea name="galleryImage_descr[{$i.id}]">{$i.descr}</textarea></td>
++                                    </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}
++        {/if}
++                    </div>
++                </td>
++            </tr>
++        </table>
++{/if} <!-- glm_members_permit_admin_member_info_edit -->
  
      <script type="text/javascript">
          jQuery(document).ready(function($) {
                  $("#newImageDialog").dialog("open");
              });
      
--            // Submit new city
--            var newImageAdded = false;
--            $('#newImageSubmit').click( function() {
--    
--/*                    
--                // Get new city name
--                var newImageName = $('#newImageName').val();
--    
--                // If no name is supplied, notify used it's required
--                if (newImageName == '') {
--                    $('#newImageNameTD').addClass('glm-form-bad-input');
--                    $('#newImageNameRequired').text('An image name is required!');
--                    return false;
--                }
--    
--                // Add new image name to the hidden field that will pass the new name to PHP.
--                $('#imageName').val(newImageName);
--                
--                // Add new image name to picklist and for storing - Only one permitted per submission
--                if (newImageAdded) {
--                    
--                    // New image already added, so just update the name and select that one
--                    $('#image').val(-1);
--                    $('#image option:selected').text(newImageName);
--                    
--                } else {
--                    
--                    // Add the new image name to the image picklist
--                    $('#image').append('<option value="-1">' + newImageName + '</option>');
--                    $('#image').val(-1);
--                    $('#newImageNameTD').append('<input type="hidden" name="newImage" value="' + newImageName + '">');
--                    newImageAdded = true;
--    
--                }
--      
--                // Clear new image name from form
--                $('#newImageName').val('');
--                
--                $("#newImageDialog").dialog("close");
--*/                
--        
--            });
--
              /*
               * Map operations
               */
               * Google Maps
               *  API reference: https://developers.google.com/maps/documentation/javascript/reference
               */
--            
++
              // Set default - Need to make this configurable
              var startLat = $('#glmLat').val();
              var startLon = $('#glmLng').val();
              var marker = new google.maps.Marker({  
                  map: map,  
                  position: location,  
--                draggable: true,
++                draggable: enableDragable,
                  animation: google.maps.Animation.DROP,  
                  title: "This is your location"  
              });  
                  glmGeocode(); 
              });
  
++            // Flash certain elements for a short time after display      
++            $(".glm-flash-updated").fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500);
++
          });
      </script>
              
@@@ -1,11 -1,10 +1,11 @@@
  <div class="wrap">
      <h2>Your Members</h2>
      <h2 class="nav-tab-wrapper">
--        <a href="{$thisURL}?page={$thisPage}&glm_action=index" class="nav-tab{if $thisAction==index}-active{/if}">Main Dashboard</a>
--        <a href="{$thisURL}?page={$thisPage}&glm_action=list" class="nav-tab{if $thisAction==list}-active{/if}">List of Members</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=index" class="nav-tab{if $thisAction==add}-active{/if} disabled">Reports</a>
 -        <a href="{$thisURL}?page={$thisPage}&glm_action=index" class="nav-tab{if $thisAction==edit}-active{else} disabled{/if}">Or Something - perahps mailing stuff?</a>
++        <a href="{$thisURL}?page={$thisPage}&glm_action=index" class="nav-tab{if $thisAction==index}-active{/if}">Dashboard</a>
++        <a href="{$thisURL}?page={$thisPage}&glm_action=list" class="nav-tab{if $thisAction==list}-active{/if}">Members List</a>
 +{foreach $addOnTabs as $a}
 +        <a href="{$thisURL}?page=glm-members-admin-menu-{$a.menu}&glm_action={$a.action}" class="nav-tab{if $thisAction==$a.action}-active{/if}">{$a.text}</a>
 +{/foreach}        
      </h2>
      <div id="glm-admin-content-container">
      
@@@ -1,53 -1,53 +1,57 @@@
  {include file='admin/members/header.html'}
      
--    <h2>Main Dashboard</h2>
++{if apply_filters('glm_members_permit_admin_members_index_add_member', true)}
++    <a href="{$thisURL}?page=glm-members-admin-menu-member&glm_action=index&" class="button-primary glm-button glm-right">Add A New Member</a>
++{/if}
++    <h2 class="glm-left">Main Dashboard</h2>
      
      <table class="glm-admin-table">
--{if $membersList}
          <tr>
              <td colspan="2" align="">
                  <input  id="glmMembersList" type="text" id="autoTest" style="margin-left: 2em;">
                  <span class="glm-left">Member Search:</span>
              </td>
          </tr>
--{/if}
--    
--{if !$haveMemberTypes}
++
++{if apply_filters('glm_members_permit_admin_members_index_member_config_warning', true)}
++  {if !$haveMemberTypes}
          <tr>
              <th class="glm-error">You do not have any Member Types setup.</th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=index">Click here to add Member Types.</a></td>
          </tr>
--{/if}                
--{if !$haveCategories}
++  {/if}                
++  {if !$haveCategories}
          <tr>
              <th><span class="glm-error">You do not have any Member Categories setup.</span></th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=categories">Click here to add Member Categories.</a></td>
          </tr>
--{/if}                
--{if !$haveAccommodationTypes}
++  {/if}                
++  {if !$haveAccommodationTypes}
          <tr>
              <th><span class="glm-error">You do not have any Accommodation Types setup.</span></th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=accommodationTypes">Click here to add Accommodation Types.</a></td>
          </tr>
--{/if}                
--{if !$haveAmenities}
++  {/if}                
++  {if !$haveAmenities}
          <tr>
              <th><span class="glm-error">You do not have any Amenities setup.</span></th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=amenities">Click here to add Amenities.</a></td>
          </tr>
--{/if}                
--{if !$haveCities}
++  {/if}                
++  {if !$haveCities}
          <tr>
              <th><span class="glm-error">You do not have any Cities setup.</span></th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=cities">Click here to add Cities.</a></td>
          </tr>
--{/if}                
--{if !$haveRegions}
++  {/if}                
++  {if !$haveRegions}
          <tr>
              <th><span class="glm-error">You do not have any Regions setup.</span></th>
              <td><a href="{$thisURL}?page=glm-members-admin-menu-configure&glm_action=regions">Click here to add Regions.</a></td>
          </tr>
--{/if}                
++  {/if}
++{/if}
++                
  {if $numbMembers == 0}
          <tr><td colspan="2">&nbsp;</td></tr>
          <tr>
@@@ -64,7 -64,7 +68,7 @@@
  {if $haveBadLatLon}
      <h3>Member Information with Bad Map Location Information</h3>
      
--    <table class="wp-list-table widefat fixed posts glm-admin-table"">
++    <table class="wp-list-table widefat fixed posts glm-admin-table">
          <thead>
              <tr>
                  <th>Member Name</th>
                  <th>Member Name</th>
                  <th>Last Updated</th>
                  <th>Reference Name</th>
--                <th>&nbsp;</th>
              </tr>
          </thead>
          <tbody>
              <tr class="alternate">
          {/if}
                  <td>
--                    <a href="{$thisURL}?page=glm-members-admin-menu-member&glm_action=memberInfo&member={$p.member_pointer}&id={$p.id}}">{$p.member}</a>
++                    <a href="{$thisURL}?page=glm-members-admin-menu-member&glm_action=memberInfo&member={$p.member_pointer}&memberInfo={$p.id}}">{$p.member}</a>
                  </td>
                  <td>
                      {$p.modify_time.datetime}
                  <td>
                      {$p.reference_name}
                  </td>
--                <td>
--                    <a href="{$thisURL}?page=glm-members-admin-menu-member&glm_action=memberInfo&member={$p.member_pointer}&id={$p.id}}" class="button-primary glm-right">Manage</a>
--                </td>
              </tr>
      {/foreach}
          </tbody>
@@@ -3,7 -3,7 +3,7 @@@
      <form class="glm-right" onSubmit="return false;">
         <span{if $haveFilter} class="glm-notice"{/if}><b>List Filters:</b>&nbsp;&nbsp;</span> 
         <input type="checkbox" id="filterArchived" class="listFilter"{if $filterArchived} checked{/if}>Show Archived&nbsp;&nbsp;
--       <input type="checkbox" id="filterPending" class="listFilter"{if $filterPending} checked{/if}>Only show Pending Information&nbsp;&nbsp;
++       <input type="checkbox" id="filterPending" class="listFilter"{if $filterPending} checked{/if}>Pending Only&nbsp;&nbsp;
          <select id="filterCategories" class="listFilter">
              <option id="categoryNone" value=""></option>
      {foreach from=$categories item=v}
          </select>
          Categories
         &nbsp;&nbsp;
--       <input type="text" id="filterName" class="listFilter" value="{$filterName}"> Search
++       <input  id="glmMembersSearch" type="text" id="autoTest"> Search
      </form>
--    
++    <br clear="all">
      <h2>List of Members</h2>
      
--    <table class="wp-list-table widefat fixed posts glm-admin-table">
++    <table class="wp-list-table striped glm-admin-table">
          <thead>
              <tr>
                  <th>ID</th>
                  <td>
                      {$m.id}
                  </td>
--                <td>
++                <td class="glm-nowrap">
                      <a href="{$thisURL}?page=glm-members-admin-menu-member&glm_action=index&member={$m.id}">{$m.name}</a>
                  </td>
--                <td>
--                    {$m.access.name}
++                <td class="glm-nowrap">
++                    {$m.access_short.name}
                  </td>
                  <td>
                      {$m.member_type.name}
      <script type="text/javascript">
          jQuery(document).ready(function($) {
              
--              // Filter triggers
--              $(".listFilter" ).change( function() {
--                      
--                      var filter = '';
--                      
--                      // Check for archived filter
--                      if ($("#filterArchived").attr('checked')) {
--                                filter += '&filterArchived=true';
--                      }
--
--                      // Check for pending data filter
++            // Filter triggers
++            $(".listFilter" ).change( function() {
++                
++                var filter = '';
++                
++                // Check for archived filter
++                if ($("#filterArchived").attr('checked')) {
++                    filter += '&filterArchived=true';
++                }
++                
++                // Check for pending data filter
                  if ($("#filterPending").attr('checked')) {
--                      filter += '&filterPending=true';
++                    filter += '&filterPending=true';
                  }
--
++                
                  // Check for category filter
                  cat = $("#filterCategories").val();
                  if (cat != '') {
--                      filter += '&filterCategory=' + cat;
++                    filter += '&filterCategory=' + cat;
                  }
++                
++                window.location.href = "{$thisURL}?page={$thisPage}&glm_action=list" + filter;
++                
++                return false;
++            });
++            
++            /*
++             * Do autocomplete search for member
++             * label: What will be searched
++             * value: What will be displayed when selected
++             * id: Member id added so we can go to the member while showing what was selected
++             * Also note that autocomplete does not properly render HTML codes, so we 
++             * "unescape" them for HTML in Smarty.
++             */
++            var availableTags = [
++    {foreach $members as $m}
++                { label: "{$m.name|unescape:'html'}", value: "{$m.name|unescape:'html'}", id: '{$m.id}' },
++    {/foreach}
++             ];
++             $( "#glmMembersSearch" ).autocomplete({
++                 source: availableTags,
++                 html: true,
++                 select: function( event, ui ) {
++                     var memberID = ui.item.id;
++                     window.location.replace("{$adminURL}?page=glm-members-admin-menu-member&glm_action=index&member=" + memberID );
++                 }
++             });
  
--                      // Check for member name filter
--                      var filterName = $("#filterName").val();
--                      if (filterName != '') {
--                              filter += '&filterName=' + encodeURIComponent(filterName).replace(/%20/g,'+');
--                      }
--                      
--                      window.location.href = "{$thisURL}?page={$thisPage}&glm_action=list" + filter;
--                      
--                      return false;
--              });
          });
      </script>