update plugins

This commit is contained in:
Tony Volpe
2024-06-17 14:42:23 -04:00
parent a00f379f7f
commit 38e314323c
9467 changed files with 2032414 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
class GFAddonLocking extends GFLocking {
protected $_strings;
/* @var GFAddOn $_addon */
protected $_addon;
/**
* e.g.
*
* array(
* "object_type" => 'contact',
* "capabilities" => array("gravityforms_contacts_edit_contacts"),
* "redirect_url" => admin_url("admin.php?page=gf_contacts"),
* "edit_url" => admin_url(sprintf("admin.php?page=gf_contacts&id=%d", $contact_id)),
* "strings" => $strings
* );
*
* @param array $config
* @param GFAddOn $addon
*/
public function __construct( $config, $addon ) {
$this->_addon = $addon;
$capabilities = isset( $config['capabilities'] ) ? $config['capabilities'] : array();
$redirect_url = isset( $config['redirect_url'] ) ? $config['redirect_url'] : '';
$edit_url = isset( $config['edit_url'] ) ? $config['edit_url'] : '';
$object_type = isset( $config['object_type'] ) ? $config['object_type'] : '';
$this->_strings = isset( $config['strings'] ) ? $config['strings'] : array();
parent::__construct( $object_type, $redirect_url, $edit_url, $capabilities );
}
public function get_strings() {
return array_merge( parent::get_strings(), $this->_strings );
}
protected function is_edit_page() {
return $this->_addon->is_locking_edit_page();
}
protected function is_list_page() {
return $this->_addon->is_locking_list_page();
}
protected function is_view_page() {
return $this->_addon->is_locking_view_page();
}
protected function get_object_id() {
return $this->_addon->get_locking_object_id();
}
protected function is_object_locked( $object_id ) {
return $this->is_object_locked( $object_id );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,334 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
class GFAutoUpgrade {
protected $_version;
protected $_min_gravityforms_version;
protected $_slug;
protected $_title;
protected $_full_path;
protected $_path;
protected $_url;
protected $_is_gravityforms_supported;
public function __construct( $slug, $version, $min_gravityforms_version, $title, $full_path, $path, $url, $is_gravityforms_supported ) {
$this->_slug = $slug;
$this->_version = $version;
$this->_min_gravityforms_version = $min_gravityforms_version;
$this->_title = $title;
$this->_full_path = $full_path;
$this->_path = $path;
$this->_url = $url;
$this->_is_gravityforms_supported = $is_gravityforms_supported;
add_action( 'init', array( $this, 'init' ) );
}
public function init() {
if ( is_admin() ) {
GFCommon::load_gf_text_domain();
add_action( 'install_plugins_pre_plugin-information', array( $this, 'display_changelog' ), 9 );
add_action( 'gform_after_check_update', array( $this, 'flush_version_info' ) );
add_action( 'gform_updates', array( $this, 'display_updates' ) );
add_filter( 'gform_updates_list', array( $this, 'get_update_info' ) );
if ( RG_CURRENT_PAGE == 'plugins.php' ) {
add_action( 'after_plugin_row_' . $this->_path, array( $this, 'rg_plugin_row' ) );
} elseif ( in_array( RG_CURRENT_PAGE, array( 'admin-ajax.php' ) ) ) {
add_action( 'wp_ajax_gf_get_changelog', array( $this, 'ajax_display_changelog' ) );
}
}
// Check for updates. The check might not run the admin context. E.g. from WP-CLI.
add_filter( 'transient_update_plugins', array( $this, 'check_update' ) );
add_filter( 'site_transient_update_plugins', array( $this, 'check_update' ) );
// ManageWP premium update filters
add_filter( 'mwp_premium_update_notification', array( $this, 'premium_update_push' ) );
add_filter( 'mwp_premium_perform_update', array( $this, 'premium_update' ) );
}
/**
* Displays messages for the Gravity Forms listing on the Plugins page.
*
* Displays if Gravity Forms isn't supported.
*
* @since Unknown
* @since 2.4.15 Update to improve multisite updates.
*/
public function rg_plugin_row() {
if ( ! $this->_is_gravityforms_supported ) {
$message = sprintf( esc_html__( 'Gravity Forms %s is required. Activate it now or %spurchase it today!%s', 'gravityforms' ), $this->_min_gravityforms_version, "<a href='https://www.gravityforms.com'>", '</a>' );
GFAddOn::display_plugin_message( $message, true );
}
}
//Integration with ManageWP
public function premium_update_push( $premium_update ) {
if ( ! function_exists( 'get_plugin_data' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
$update = $this->get_version_info( $this->_slug );
if ( rgar( $update, 'is_valid_key' ) == true && version_compare( $this->_version, $update['version'], '<' ) ) {
$plugin_data = get_plugin_data( $this->_full_path );
$plugin_data['type'] = 'plugin';
$plugin_data['slug'] = $this->_path;
$plugin_data['new_version'] = isset( $update['version'] ) ? $update['version'] : false;
$premium_update[] = $plugin_data;
}
return $premium_update;
}
//Integration with ManageWP
public function premium_update( $premium_update ) {
if ( ! function_exists( 'get_plugin_data' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
$update = $this->get_version_info( $this->_slug );
if ( rgar( $update, 'is_valid_key' ) == true && version_compare( $this->_version, $update['version'], '<' ) ) {
$plugin_data = get_plugin_data( $this->_full_path );
$plugin_data['slug'] = $this->_path;
$plugin_data['type'] = 'plugin';
$plugin_data['url'] = isset( $update['url'] ) ? $update['url'] : false; // OR provide your own callback function for managing the update
array_push( $premium_update, $plugin_data );
}
return $premium_update;
}
public function flush_version_info() {
$this->set_version_info( $this->_slug, false );
}
private function set_version_info( $plugin_slug, $version_info ) {
if ( function_exists( 'set_site_transient' ) ) {
set_site_transient( $plugin_slug . '_version', $version_info, 60 * 60 * 12 );
} else {
set_transient( $plugin_slug . '_version', $version_info, 60 * 60 * 12 );
}
}
public function check_update( $option ) {
if ( empty( $option ) ) {
return $option;
}
$key = $this->get_key();
$version_info = $this->get_version_info( $this->_slug );
if ( rgar( $version_info, 'is_error' ) == '1' ) {
return $option;
}
if ( empty( $option->response[ $this->_path ] ) ) {
$option->response[ $this->_path ] = new stdClass();
}
$plugin = array(
'plugin' => $this->_path,
'url' => $this->_url,
'slug' => $this->_slug,
'package' => $version_info['url'] ? str_replace( '{KEY}', $key, $version_info['url'] ) : '',
'new_version' => $version_info['version'],
'id' => '0',
);
//Empty response means that the key is invalid. Do not queue for upgrade
if ( ! rgar( $version_info, 'is_valid_key' ) || version_compare( $this->_version, $version_info['version'], '>=' ) ) {
unset( $option->response[ $this->_path ] );
$option->no_update[ $this->_path ] = (object) $plugin;
} else {
$option->response[ $this->_path ] = (object) $plugin;
}
return $option;
}
// Displays current version details on plugins page and updates page
public function display_changelog() {
if ( $_REQUEST['plugin'] != $this->_slug ) {
return;
}
$change_log = $this->get_changelog();
echo $change_log;
exit;
}
/**
* Get changelog with admin-ajax.php in GFForms::maybe_display_update_notification().
*
* @since 2.4.15
*/
public function ajax_display_changelog() {
check_admin_referer();
$this->display_changelog();
}
private function get_changelog() {
$key = $this->get_key();
$body = "key={$key}";
$options = array( 'method' => 'POST', 'timeout' => 3, 'body' => $body );
$options['headers'] = array(
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ),
'Content-Length' => strlen( $body ),
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
);
$raw_response = GFCommon::post_to_manager( 'changelog.php', $this->get_remote_request_params( $this->_slug, $key, $this->_version ), $options );
if ( is_wp_error( $raw_response ) || 200 != $raw_response['response']['code'] ) {
$text = sprintf( esc_html__( 'Oops!! Something went wrong.%sPlease try again or %scontact us%s.', 'gravityforms' ), '<br/>', "<a href='" . esc_attr( GFCommon::get_support_url() ). "'>", '</a>' );
} else {
$text = $raw_response['body'];
if ( substr( $text, 0, 10 ) != '<!--GFM-->' ) {
$text = '';
}
}
return stripslashes( $text );
}
private function get_version_info( $offering, $use_cache = true ) {
$version_info = GFCommon::get_version_info( $use_cache );
$is_valid_key = rgar( $version_info, 'is_valid_key' ) && rgars( $version_info, "offerings/{$offering}/is_available" );
$info = array( 'is_valid_key' => $is_valid_key, 'version' => rgars( $version_info, "offerings/{$offering}/version" ), 'url' => rgars( $version_info, "offerings/{$offering}/url" ) );
return $info;
}
private function get_remote_request_params( $offering, $key, $version ) {
global $wpdb;
return sprintf( 'of=%s&key=%s&v=%s&wp=%s&php=%s&mysql=%s', urlencode( $offering ), urlencode( $key ), urlencode( $version ), urlencode( get_bloginfo( 'version' ) ), urlencode( phpversion() ), urlencode( GFCommon::get_db_version() ) );
}
private function get_key() {
if ( $this->_is_gravityforms_supported ) {
return GFCommon::get_key();
} else {
return '';
}
}
public function get_update_info( $updates ) {
$force_check = rgget( 'force-check' ) == 1;
$version_info = $this->get_version_info( $this->_slug, ! $force_check );
$plugin_file = $this->_path;
$upgrade_url = wp_nonce_url( 'update.php?action=upgrade-plugin&amp;plugin=' . urlencode( $plugin_file ), 'upgrade-plugin_' . $plugin_file );
if ( ! rgar( $version_info, 'is_valid_key' ) ) {
$version_icon = 'dashicons-no';
$version_message = sprintf(
'<p>%s</p>',
sprintf(
esc_html( '%sRegister%s your copy of Gravity Forms to receive access to automatic updates and support. Need a license key? %sPurchase one now%s.', 'gravityforms' ),
'<a href="admin.php?page=gf_settings">',
'</a>',
'<a href="https://www.gravityforms.com">',
'</a>'
)
);
} elseif ( version_compare( $this->_version, $version_info['version'], '<' ) ) {
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . urlencode( $this->_slug ) . '&section=changelog&TB_iframe=true&width=600&height=800' );
$message_link_text = sprintf( esc_html__( 'View version %s details', 'gravityforms' ), $version_info['version'] );
$message_link = sprintf( '<a href="%s" class="thickbox" title="%s">%s</a>', esc_url( $details_url ), esc_attr( $this->_title ), $message_link_text );
$message = sprintf( esc_html__( 'There is a new version of %1$s available. %s.', 'gravityforms' ), $this->_title, $message_link );
$version_icon = 'dashicons-no';
$version_message = $message;
} else {
$version_icon = 'dashicons-yes';
$version_message = sprintf( esc_html__( 'Your version of %s is up to date.', 'gravityforms' ), $this->_title );
}
$updates[] = array(
'name' => esc_html( $this->_title ),
'is_valid_key' => rgar( $version_info, 'is_valid_key' ),
'path' => $this->_path,
'slug' => $this->_slug,
'latest_version' => $version_info['version'],
'installed_version' => $this->_version,
'upgrade_url' => $upgrade_url,
'download_url' => $version_info['url'],
'version_icon' => $version_icon,
'version_message' => $version_message,
);
return $updates;
}
public function display_updates() {
?>
<div class="wrap <?php echo GFCommon::get_browser_class() ?>">
<h2><?php esc_html_e( $this->_title ); ?></h2>
<?php
$force_check = rgget( 'force-check' ) == 1;
$version_info = $this->get_version_info( $this->_slug, ! $force_check );
if ( ! rgar( $version_info, 'is_valid_key' ) ) {
?>
<div class="gf_update_expired alert_red">
<?php printf( esc_html__( '%sRegister%s your copy of Gravity Forms to receive access to automatic updates and support. Need a license key? %sPurchase one now%s.', 'gravityforms' ), '<a href="admin.php?page=gf_settings">','</a>','<a href="https://www.gravityforms.com">', '</a>' ); ?>
</div>
<?php
} elseif ( version_compare( $this->_version, $version_info['version'], '<' ) ) {
if ( rgar( $version_info, 'is_valid_key' ) ) {
$plugin_file = $this->_path;
$upgrade_url = wp_nonce_url( 'update.php?action=upgrade-plugin&amp;plugin=' . urlencode( $plugin_file ), 'upgrade-plugin_' . $plugin_file );
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . urlencode( $this->_slug ) . '&section=changelog&TB_iframe=true&width=600&height=800' );
$message_link_text = sprintf( esc_html__( 'View version %s details', 'gravityforms' ), $version_info['version'] );
$message_link = sprintf( '<a href="%s" class="thickbox" title="%s">%s</a>', esc_url( $details_url ), esc_attr( $this->_title ), $message_link_text );
$message = sprintf( esc_html__( 'There is a new version of %1$s available. %s.', 'gravityforms' ), $this->_title, $message_link );
?>
<div class="gf_update_outdated alert_yellow">
<?php echo $message . ' <p>' . sprintf( esc_html__( 'You can update to the latest version automatically or download the update and install it manually. %sUpdate Automatically%s %sDownload Update%s', 'gravityforms' ), "</p><a class='button-primary' href='{$upgrade_url}'>", '</a>', "&nbsp;<a class='button' href='{$version_info['url']}'>", '</a>' ); ?>
</div>
<?php
}
} else {
?>
<div class="gf_update_current alert_green">
<?php printf( esc_html__( 'Your version of %s is up to date.', 'gravityforms' ), $this->_title ); ?>
</div>
<?php
}
?>
</div>
<?php
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,310 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
if ( ! class_exists( 'GF_Background_Process' ) ) {
require_once GF_PLUGIN_DIR_PATH . 'includes/libraries/gf-background-process.php';
}
/**
* GF_Feed_Processor Class.
*
* @since 2.2
*/
class GF_Feed_Processor extends GF_Background_Process {
/**
* Contains an instance of this class, if available.
*
* @since 2.2
* @access private
* @var object $_instance If available, contains an instance of this class.
*/
private static $_instance = null;
/**
* The action name.
*
* @since 2.2
* @access protected
* @var string
*/
protected $action = 'gf_feed_processor';
/**
* Get instance of this class.
*
* @since 2.2
* @access public
* @static
*
* @return GF_Feed_Processor
*/
public static function get_instance() {
if ( null === self::$_instance ) {
self::$_instance = new self;
}
return self::$_instance;
}
/**
* Task
*
* @since 2.2
* @access protected
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param array $item The task arguments: addon, feed, entry_id, and form_id.
*
* @return bool
*/
protected function task( $item ) {
$addon = $item['addon'];
$feed = $item['feed'];
$feed_name = rgars( $feed, 'meta/feed_name' ) ? $feed['meta']['feed_name'] : rgars( $feed, 'meta/feedName' );
$callable = array( is_string( $addon ) ? $addon : get_class( $addon ), 'get_instance' );
if ( is_callable( $callable ) ) {
$addon = call_user_func( $callable );
}
if ( ! $addon instanceof GFFeedAddOn ) {
GFCommon::log_error( __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$item['entry_id']} for {$feed['addon_slug']} but add-on could not be found. Bailing." );
return false;
}
$entry = GFAPI::get_entry( $item['entry_id'] );
$addon_slug = $addon->get_slug();
// Remove task if entry cannot be found.
if ( is_wp_error( $entry ) ) {
call_user_func( array(
$addon,
'log_debug',
), __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$item['entry_id']} for {$addon_slug} but entry could not be found. Bailing." );
return false;
}
$processed_feeds = $addon->get_feeds_by_entry( $entry['id'] );
if ( is_array( $processed_feeds ) && in_array( $feed['id'], $processed_feeds ) ) {
call_user_func( array(
$addon,
'log_debug',
), __METHOD__ . "(): already processed feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon_slug}. Bailing." );
return false;
}
$item = $this->increment_attempts( $item );
$max_attempts = 1;
$form = $this->filter_form( GFAPI::get_form( $item['form_id'] ), $entry );
/**
* Allow the number of retries to be modified before the feed is abandoned.
*
* if $max_attempts > 1 and if GFFeedAddOn::process_feed() throws an error or returns a WP_Error then the feed
* will be attempted again. Once the maximum number of attempts has been reached then the feed will be abandoned.
*
* @since 2.4
*
* @param int $max_attempts The maximum number of retries allowed. Default: 1.
* @param array $form The form array
* @param array $entry The entry array
* @param string $addon_slug The add-on slug
* @param array $feed The feed array
*/
$max_attempts = apply_filters( 'gform_max_async_feed_attempts', $max_attempts, $form, $entry, $addon_slug, $feed );
// Remove task if it was attempted too many times but failed to complete.
if ( $item['attempts'] > $max_attempts ) {
call_user_func( array(
$addon,
'log_debug',
), __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon->get_slug()} too many times. Bailing." );
return false;
}
// Use the add-on to log the start of feed processing.
call_user_func( array(
$addon,
'log_debug',
), __METHOD__ . "(): Starting to process feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$addon->get_slug()}. Attempt number: " . $item['attempts'] );
try {
// Maybe convert PHP errors to exceptions so that they get caught.
// This will catch some fatal errors, but not all.
// Errors that are not caught will halt execution of subsequent feeds, but those will be
// executed during the next cron cycles, which happens every 5 minutes
set_error_handler( array( $this, 'custom_error_handler' ) );
// Process feed.
$returned_entry = call_user_func( array( $addon, 'process_feed' ), $feed, $entry, $form );
// Back to built-in error handler.
restore_error_handler();
} catch ( Exception $e ) {
// Back to built-in error handler.
restore_error_handler();
// Log the exception.
call_user_func( array(
$addon,
'log_error',
), __METHOD__ . "(): Unable to process feed due to error: {$e->getMessage()}" );
// Return the item for another attempt
return $item;
}
if ( is_wp_error( $returned_entry ) ) {
/** @var WP_Error $returned_entry */
// Log the error.
call_user_func( array(
$addon,
'log_error',
), __METHOD__ . "(): Unable to process feed due to error: {$returned_entry->get_error_message()}" );
// Return the item for another attempt
return $item;
}
// If returned value from the process feed call is an array containing an ID, update entry and set the entry to its value.
if ( is_array( $returned_entry ) && rgar( $returned_entry, 'id' ) ) {
// Set entry to returned entry.
$entry = $returned_entry;
// Save updated entry.
if ( $entry !== $returned_entry ) {
GFAPI::update_entry( $entry );
}
}
/**
* Perform a custom action when a feed has been processed.
*
* @since 2.0
*
* @param array $feed The feed which was processed.
* @param array $entry The current entry object, which may have been modified by the processed feed.
* @param array $form The current form object.
* @param GFAddOn $addon The current instance of the GFAddOn object which extends GFFeedAddOn or GFPaymentAddOn (i.e. GFCoupons, GF_User_Registration, GFStripe).
*/
do_action( 'gform_post_process_feed', $feed, $entry, $form, $addon );
do_action( "gform_{$feed['addon_slug']}_post_process_feed", $feed, $entry, $form, $addon );
// Log that Add-On has been fulfilled.
call_user_func( array(
$addon,
'log_debug',
), __METHOD__ . '(): Marking entry #' . $entry['id'] . ' as fulfilled for ' . $feed['addon_slug'] );
gform_update_meta( $entry['id'], "{$feed['addon_slug']}_is_fulfilled", true );
// Get current processed feeds.
$meta = gform_get_meta( $entry['id'], 'processed_feeds' );
// If no feeds have been processed for this entry, initialize the meta array.
if ( empty( $meta ) ) {
$meta = array();
}
// Add this feed to this Add-On's processed feeds.
$meta[ $feed['addon_slug'] ][] = $feed['id'];
// Update the entry meta.
gform_update_meta( $entry['id'], 'processed_feeds', $meta );
return false;
}
/**
* Custom error handler to convert any errors to an exception.
*
* @since 2.2
* @since 2.6.5 Removed the $context param.
* @access public
*
* @param int $number The level of error raised.
* @param string $string The error message, as a string.
* @param string $file The filename the error was raised in.
* @param int $line The line number the error was raised at.
* @param array $context An array that points to the active symbol table at the point the error occurred.
*
* @throws ErrorException
*
* @return false
*/
public function custom_error_handler( $number, $string, $file, $line ) {
// Determine if this error is one of the enabled ones in php config (php.ini, .htaccess, etc).
$error_is_enabled = (bool) ( $number & ini_get( 'error_reporting' ) );
// Throw an Error Exception, to be handled by whatever Exception handling logic is available in this context.
if ( in_array( $number, array( E_USER_ERROR, E_RECOVERABLE_ERROR ) ) && $error_is_enabled ) {
throw new ErrorException( $string, 0, $number, $file, $line );
} elseif ( $error_is_enabled ) {
// Log the error if it's enabled. Otherwise, just ignore it.
error_log( $string, 0 );
// Make sure this ends up in $php_errormsg, if appropriate.
return false;
}
}
protected function increment_attempts( $item ) {
$batch = $this->get_batch();
$item_feed = rgar( $item, 'feed' );
$item_entry_id = rgar( $item, 'entry_id' );
foreach ( $batch->data as $key => $task ) {
$task_feed = rgar( $task, 'feed' );
$task_entry_id = rgar( $task, 'entry_id' );
if ( $item_feed['id'] === $task_feed['id'] && $item_entry_id === $task_entry_id ) {
$batch->data[ $key ]['attempts'] = isset( $batch->data[ $key ]['attempts'] ) ? $batch->data[ $key ]['attempts'] + 1 : 1;
$item['attempts'] = $batch->data[ $key ]['attempts'];
break;
}
}
$this->update( $batch->key, $batch->data );
return $item;
}
}
/**
* Returns an instance of the GF_Feed_Processor class
*
* @see GF_Feed_Processor::get_instance()
* @return GF_Feed_Processor
*/
function gf_feed_processor() {
return GF_Feed_Processor::get_instance();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,927 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
if ( ! class_exists( 'GFResults' ) ) {
class GFResults {
protected $_slug;
protected $_title;
protected $_icon;
protected $_callbacks;
protected $_capabilities;
protected $_search_title;
public function __construct( $slug, $config ) {
$this->_slug = $slug;
$this->_title = rgar( $config, 'title' );
$this->_icon = rgar( $config, 'icon' );
$this->_search_title = rgempty( 'search_title', $config ) ? esc_html__( 'Results Filters', 'gravityforms' ) : rgar( $config, 'search_title' );
$this->_callbacks = isset( $config['callbacks'] ) ? $config['callbacks'] : array();
$this->_capabilities = isset( $config['capabilities'] ) ? $config['capabilities'] : array();
}
public function init() {
if ( ! GFCommon::current_user_can_any( $this->_capabilities ) ) {
return;
}
// is any GF page
if ( GFForms::is_gravity_page() ) {
// add top toolbar menu item
add_filter( 'gform_toolbar_menu', array( $this, 'add_toolbar_menu_item' ), 10, 2 );
// add custom form action
add_filter( 'gform_form_actions', array( $this, 'add_form_action' ), 10, 2 );
}
// is results page
if ( rgget( 'view' ) == "gf_results_{$this->_slug}" ) {
// add the results view
add_action( 'gform_entries_view', array( $this, 'add_view' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
// tooltips
require_once( GFCommon::get_base_path() . '/tooltips.php' );
add_filter( 'gform_tooltips', array( $this, 'add_tooltips' ) );
}
}
public function enqueue_admin_scripts() {
wp_enqueue_script( 'jquery-ui-resizable' );
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_script( 'google_charts' );
wp_enqueue_style( 'gaddon_results_css' );
wp_enqueue_script( 'gaddon_results_js' );
$this->localize_results_scripts();
}
public static function localize_results_scripts() {
// Get current page protocol
$protocol = isset( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
// Output admin-ajax.php URL with same protocol as current page
$vars = array(
'ajaxurl' => admin_url( 'admin-ajax.php', $protocol ),
'imagesUrl' => GFCommon::get_base_url() . '/images'
);
wp_localize_script( 'gaddon_results_js', 'gresultsVars', $vars );
$strings = array(
'ajaxError' => wp_strip_all_tags( __( 'Error retrieving results. If the problem persists, please contact support.', 'gravityforms' ) )
);
wp_localize_script( 'gaddon_results_js', 'gresultsStrings', $strings );
}
private function get_fields( $form ) {
return isset( $this->_callbacks['fields'] ) ? call_user_func( $this->_callbacks['fields'], $form ) : $form['fields'];
}
public function add_form_action( $actions, $form_id ) {
return $this->filter_menu_items( $actions, $form_id, true );
}
public function add_toolbar_menu_item( $menu_items, $form_id ) {
return $this->filter_menu_items( $menu_items, $form_id, false );
}
public function filter_menu_items( $menu_items, $form_id, $compact ) {
$form_meta = GFFormsModel::get_form_meta( $form_id );
$results_fields = $this->get_fields( $form_meta );
if ( false === empty( $results_fields ) ) {
$form_id = $form_meta['id'];
$link_class = '';
if ( rgget( 'page' ) == 'gf_new_form' ) {
$link_class = 'gf_toolbar_disabled';
} elseif ( rgget( 'page' ) == 'gf_entries' && rgget( 'view' ) == 'gf_results_' . $this->_slug ) {
$link_class = 'gf_toolbar_active';
}
$id = rgget( 'id' );
if ( empty( $id ) ) {
//on the form list page, do not use icons.
$icon = '';
} else {
$icon = $this->_icon;
if ( empty( $icon ) ) {
$icon = '<i class="fa fa-bar-chart-o fa-lg"></i>';
}
}
$sub_menu_items = array();
$sub_menu_items[] = array(
'label' => $this->_title,
'icon' => $icon,
'title' => esc_html__( 'View results generated by this form', 'gravityforms' ),
'link_class' => $link_class,
'url' => admin_url( "admin.php?page=gf_entries&view=gf_results_{$this->_slug}&id={$form_id}" ),
'capabilities' => $this->_capabilities,
);
$duplicate_submenus = wp_filter_object_list( rgars( $menu_items, 'results/sub_menu_items' ), array( 'label' => $sub_menu_items[0]['label'] ) );
if ( count( $duplicate_submenus ) > 0 ) {
return $menu_items;
}
// If there's already a menu item with the key "results" then merge the two.
if ( isset( $menu_items['results'] ) ) {
$existing_link_class = $menu_items['results']['link_class'];
$link_class == empty( $existing_link_class ) ? $link_class : $existing_link_class;
$existing_capabilities = $menu_items['results']['capabilities'];
$merged_capabilities = array_merge( $existing_capabilities, $this->_capabilities );
$existing_sub_menu_items = isset( $menu_items['results']['sub_menu_items'] ) ? $menu_items['results']['sub_menu_items'] : $menu_items['results']['single_menu_item'];
$merged_sub_menu_items = array_merge( $existing_sub_menu_items, $sub_menu_items );
$menu_items['results']['link_class'] = $link_class;
$menu_items['results']['capabilities'] = $merged_capabilities;
$menu_items['results']['sub_menu_items'] = $merged_sub_menu_items;
$menu_items['results']['label'] = esc_html__( 'Results', 'gravityforms' );
$menu_items['results']['icon'] = '<i class="fa fa-bar-chart-o fa-lg"></i>';
} else {
// so far during the page cycle this is the only menu item for this key.
$menu_items['results'] = array(
'label' => $compact ? esc_html__( 'Results', 'gravityforms' ) : $this->_title,
'icon' => $icon,
'title' => esc_attr__( 'View results generated by this form', 'gravityforms' ),
'url' => admin_url( "admin.php?page=gf_entries&view=gf_results_{$this->_slug}&id={$form_id}" ),
'menu_class' => 'gf_form_toolbar_results',
'link_class' => $link_class,
'capabilities' => $this->_capabilities,
'single_menu_item' => $sub_menu_items,
'priority' => 750,
);
}
}
return $menu_items;
}
public function add_view( $view, $form_id ) {
if ( $view == 'gf_results_' . $this->_slug ) {
$form_id = absint( $form_id );
GFResults::results_page( $form_id, $this->_title, 'gf_entries', $view );
}
}
public function results_page( $form_id, $page_title, $gf_page, $gf_view ) {
$form_id = absint( $form_id );
if ( empty( $form_id ) ) {
$forms = RGFormsModel::get_forms();
if ( ! empty( $forms ) ) {
$form_id = $forms[0]->id;
}
}
$form = GFFormsModel::get_form_meta( $form_id );
$form = gf_apply_filters( array( 'gform_form_pre_results', $form_id ), $form );
// Set up filter vars
$start_date = preg_replace( '/[^0-9-]/', '', rgget( 'start' ) );
$end_date = preg_replace( '/[^0-9-]/', '', rgget( 'end' ) );
$all_fields = $form['fields'];
$filter_settings = GFCommon::get_field_filter_settings( $form );
$filter_settings = apply_filters( 'gform_filters_pre_results', $filter_settings, $form );
$filter_settings = array_values( $filter_settings ); // reset the numeric keys in case some filters have been unset
$filter_fields = rgget( 'f' );
$filter_operators = rgget( 'o' );
$filter_values = rgget( 'v' );
$filters = array();
$init_vars = array();
if ( ! empty( $filter_fields ) ) {
$init_vars['mode'] = rgget( 'mode' );
foreach ( $filter_fields as $i => $filter_field ) {
$filters[ $i ]['field'] = $filter_field;
$filters[ $i ]['operator'] = $filter_operators[ $i ];
$filters[ $i ]['value'] = $filter_values[ $i ];
}
$init_vars['filters'] = $filters;
}
?>
<script type="text/javascript">
var gresultsFields = <?php echo json_encode( $all_fields ); ?>;
var gresultsFilterSettings = <?php echo json_encode( $filter_settings ); ?>;
var gresultsInitVars = <?php echo json_encode( $init_vars ); ?>;
<?php GFCommon::gf_global() ?>
<?php GFCommon::gf_vars() ?>
</script>
<div class="wrap gforms_edit_form <?php echo GFCommon::get_browser_class() ?>">
<?php //GFCommon::form_page_title( $form ); ?>
<?php //GFCommon::display_dismissible_message(); ?>
<?php //GFForms::top_toolbar(); ?>
<?php GFForms::admin_header(array(), true ) ;?>
<?php if ( false === empty( $all_fields ) ) : ?>
<div id="poststuff" class="metabox-holder has-right-sidebar">
<div id="side-info-column" class="inner-sidebar">
<div id="gresults-results-filter" class="gform-settings-panel__content postbox">
<h2><?php echo $this->_search_title ?></h2>
<div id="gresults-results-filter-content">
<form id="gresults-results-filter-form" action="" method="GET">
<?php wp_nonce_field( 'gf_results', '_gf_results_nonce' ); ?>
<input type="hidden" id="gresults-page-slug" name="page"
value="<?php echo esc_attr( $gf_page ); ?>">
<input type="hidden" id="gresults-view-slug" name="view"
value="<?php echo esc_attr( $gf_view ); ?>">
<input type="hidden" id="gresults-form-id" name="id"
value="<?php echo esc_attr( $form_id ); ?>">
<?php
$filter_ui = array(
'fields' => array(
'label' => esc_attr__( 'Include results if', 'gravityforms' ),
'tooltip' => 'gresults_filters',
'markup' => '<div class="gform-settings-field__conditional-logic"><div id="gresults-results-field-filters-container">
<!-- placeholder populated by js -->
</div></div>',
),
'start_date' => array(
'label' => esc_attr__( 'Start date', 'gravityforms' ),
'markup' => '<div class="gform-settings-field gform-settings-field__date_time">
<span class="gform-settings-input__container"><input type="text" id="gresults-results-filter-date-start" name="start" value="' . esc_attr( $start_date ) . '"/><button type="button" class="ui-datepicker-trigger"><span class="screen-reader-text">'.esc_html__( 'Open Date Picker', 'gravityforms' ).'</span><svg width="18" height="18" role="presentation" focusable="false" fill="#9092B2" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13.0909 1.6364V1.231C13.0909.5513 13.6357 0 14.3182 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h.8254c.8997 0 1.6291.7349 1.6291 1.6288v13.106C18 17.2707 17.2721 18 16.3709 18H1.6291C.7294 18 0 17.2651 0 16.3712V3.2652c0-.8996.728-1.6288 1.6291-1.6288h.8254V1.231C2.4545.5513 2.9993 0 3.6818 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h2.4545V1.231C7.3636.5513 7.9084 0 8.591 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h3.2727zM1.6364 7.3636v9h14.7272v-9H1.6364z"></path></svg></button></span>
</div>',
),
'end_date' => array(
'label' => esc_attr__( 'End date', 'gravityforms' ),
'markup' => '<div class="gform-settings-field gform-settings-field__date_time" >
<span class="gform-settings-input__container"><input type="text" id="gresults-results-filter-date-end" name="end" value="' . esc_attr( $end_date ) . '"/><button type="button" class="ui-datepicker-trigger"><span class="screen-reader-text">'.esc_html__( 'Open Date Picker', 'gravityforms' ).'</span><svg width="18" height="18" role="presentation" focusable="false" fill="#9092B2" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13.0909 1.6364V1.231C13.0909.5513 13.6357 0 14.3182 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h.8254c.8997 0 1.6291.7349 1.6291 1.6288v13.106C18 17.2707 17.2721 18 16.3709 18H1.6291C.7294 18 0 17.2651 0 16.3712V3.2652c0-.8996.728-1.6288 1.6291-1.6288h.8254V1.231C2.4545.5513 2.9993 0 3.6818 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h2.4545V1.231C7.3636.5513 7.9084 0 8.591 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h3.2727zM1.6364 7.3636v9h14.7272v-9H1.6364z"></path></svg></button></span>
</div>',
),
);
$filter_ui = apply_filters( 'gform_filter_ui', $filter_ui, $form_id, $page_title, $gf_page, $gf_view );
foreach ( $filter_ui as $name => $filter ) {
?>
<div class="gform-settings-field__header"><label class='gform-settings-label'><?php echo $filter['label'] ?><?php gform_tooltip( rgar( $filter, 'tooltip' ), 'tooltip_bottomleft' ) ?></label></div>
<?php
echo $filter['markup'];
}
?>
<div id="gresults-results-filter-buttons">
<input type="submit" id="gresults-results-filter-submit-button"
class="button primary large"
value="<?php esc_attr_e( 'Apply filters', 'gravityforms' ); ?>">
<input type="button" id="gresults-results-filter-clear-button"
class="button large"
value="<?php esc_attr_e( 'Clear', 'gravityforms' ); ?>"
onclick="gresults.clearFilterForm();"
onkeypress="gresults.clearFilterForm();">
<div class="gresults-filter-loading"
style="display:none; float:right; margin-top:5px;">
<i class='gform-spinner'></i>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="gresults-filter-loading" style="display:none;margin:0 5px 10px 0;">
<i class='gform-spinner'></i>&nbsp;
<a href="javascript:void(0);" onclick="javascript:gresultsAjaxRequest.abort()" onkeypress="javascript:gresultsAjaxRequest.abort()"><?php esc_html_e( 'Cancel', 'gravityforms' ); ?></a>
</div>
<div id="gresults-results-wrapper">
<div id="gresults-results">&nbsp;
</div>
</div>
<?php
else :
_e( 'This form does not have any fields that can be used for results', 'gravityforms' );
endif ?>
</div>
<?php GFForms::admin_footer() ?>
<?php
}
public static function add_tooltips( $tooltips ) {
$tooltips['gresults_total_score'] = '<h6>' . esc_html__( 'Total Score', 'gravityforms' ) . '</h6>' . esc_html__( 'Scores are weighted calculations. Items ranked higher are given a greater score than items that are ranked lower. The total score for each item is the sum of the weighted scores.', 'gravityforms' );
$tooltips['gresults_agg_rank'] = '<h6>' . esc_html__( 'Aggregate Rank', 'gravityforms' ) . '</h6>' . esc_html__( 'The aggregate rank is the overall rank for all entries based on the weighted scores for each item.', 'gravityforms' );
$tooltips['gresults_date_range'] = '<h6>' . esc_html__( 'Date Range', 'gravityforms' ) . '</h6>' . esc_html__( 'Date Range is optional, if no date range is specified it will be ignored.', 'gravityforms' );
$tooltips['gresults_filters'] = '<h6>' . esc_html__( 'Filters', 'gravityforms' ) . '</h6>' . esc_html__( 'Narrow the results by adding filters. Note that some field types support more options than others.', 'gravityforms' );
$tooltips['gresults_average_row_score'] = '<h6>' . esc_html__( 'Average Row Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score for each row: the sum of all the scores for each row divided by the total number of entries.', 'gravityforms' );
$tooltips['gresults_average_global_score'] = '<h6>' . esc_html__( 'Average Global Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score for the whole field. The sum of the total scores divided by the number of entries.', 'gravityforms' );
$tooltips['gresults_average_score'] = '<h6>' . esc_html__( 'Average Score', 'gravityforms' ) . '</h6>' . esc_html__( 'The average (mean) score: The sum of the scores divided by the number of entries.', 'gravityforms' );
return $tooltips;
}
public function ajax_get_results() {
check_ajax_referer( 'gf_results', '_gf_results_nonce' );
if ( ! GFAPI::current_user_can_any( $this->_capabilities ) ) {
wp_die( 'Not allowed' );
}
// tooltips
require_once( GFCommon::get_base_path() . '/tooltips.php' );
add_filter( 'gform_tooltips', array( $this, 'add_tooltips' ) );
$output = array();
$html = '';
$form_id = rgpost( 'id' );
$form_id = absint( $form_id );
$form = GFFormsModel::get_form_meta( $form_id );
$form = gf_apply_filters( array( 'gform_form_pre_results', $form_id ), $form );
$search_criteria['status'] = 'active';
$fields = $this->get_fields( $form );
$total_entries = GFAPI::count_entries( $form_id, $search_criteria );
if ( $total_entries == 0 ) {
$html = esc_html__( 'No results.', 'gravityforms' );
} else {
$search_criteria = array();
$search_criteria['field_filters'] = GFCommon::get_field_filters_from_post( $form );
$start_date = preg_replace( '/[^0-9-]/', '', rgpost( 'start' ) );
$end_date = preg_replace( '/[^0-9-]/', '', rgpost( 'end' ) );
if ( $start_date ) {
$search_criteria['start_date'] = $start_date;
}
if ( $end_date ) {
$search_criteria['end_date'] = $end_date;
}
$search_criteria['status'] = 'active';
$output['s'] = http_build_query( $search_criteria );
$state_array = null;
if ( isset( $_POST['state'] ) ) {
$state = $_POST['state'];
$posted_check_sum = rgpost( 'checkSum' );
$generated_check_sum = self::generate_checksum( $state );
$state_array = json_decode( base64_decode( $state ), true );
if ( $generated_check_sum !== $posted_check_sum ) {
$output['status'] = 'complete';
$output['html'] = esc_html__( 'There was an error while processing the entries. Please contact support.', 'gravityforms' );
echo json_encode( $output );
die();
}
}
$data = isset( $this->_callbacks['data'] ) ? call_user_func( $this->_callbacks['data'], $form, $fields, $search_criteria, $state_array ) : $this->get_results_data( $form, $fields, $search_criteria, $state_array );
$entry_count = $data['entry_count'];
if ( 'incomplete' === rgar( $data, 'status' ) ) {
$state = base64_encode( json_encode( $data ) );
$output['status'] = 'incomplete';
$output['stateObject'] = $state;
$output['checkSum'] = self::generate_checksum( $state );
$output['html'] = sprintf( esc_html__( 'Entries processed: %1$d of %2$d', 'gravityforms' ), rgar( $data, 'offset' ), $entry_count );
echo json_encode( $output );
die();
}
if ( $total_entries > 0 ) {
$html = isset( $this->_callbacks['markup'] ) ? call_user_func( $this->_callbacks['markup'], $html, $data, $form, $fields ) : '';
if ( empty( $html ) ) {
foreach ( $fields as $field ) {
$field_id = $field->id;
$html .= "<div class='gresults-results-field gform-settings-panel' id='gresults-results-field-{$field_id}'>";
$html .= "<header class='gform-settings-panel__header'><legend class='gform-settings-panel__title'>" . esc_html( GFCommon::get_label( $field ) ) . '</legend></header>';
$html .= '<div class="gform-settings-panel__content">' . self::get_field_results( $form_id, $data, $field, $search_criteria ) . '</div>';
$html .= '</div>';
}
}
} else {
$html .= esc_html__( 'No results', 'gravityforms' );
}
}
$output['html'] = $html;
$output['status'] = 'complete';
$output['searchCriteria'] = $search_criteria;
echo json_encode( $output );
die();
}
public function ajax_get_more_results() {
check_ajax_referer( 'gf_results', '_gf_results_nonce' );
if ( ! GFAPI::current_user_can_any( $this->_capabilities ) ) {
wp_die( 'Not allowed' );
}
$form_id = rgpost( 'form_id' );
$field_id = rgpost( 'field_id' );
$offset = rgpost( 'offset' );
$search_criteria = rgpost( 'search_criteria' );
if ( empty( $search_criteria ) ) {
$search_criteria = array();
}
$page_size = 10;
$form = RGFormsModel::get_form_meta( $form_id );
$form_id = $form['id'];
$field = RGFormsModel::get_field( $form, $field_id );
$more_remaining = false;
$html = self::get_default_field_results( $form_id, $field, $search_criteria, $offset, $page_size, $more_remaining );
$response = array();
$response['more_remaining'] = $more_remaining;
$response['html'] = $html;
$response['offset'] = $offset;
echo json_encode( $response );
die();
}
private static function generate_checksum( $data ) {
return wp_hash( crc32( ( $data ) ) );
}
public static function get_total_entries( $form ) {
$totals = RGFormsModel::get_form_counts( $form['id'] );
return $totals['total'];
}
public static function get_field_results( $form_id, $data, $field, $search_criteria ) {
if ( empty( $data['entry_count'] ) || empty ( $data['field_data'] ) ) {
return esc_html__( 'No entries for this field', 'gravityforms' );
}
$field_data = $data['field_data'];
$entry_count = $data['entry_count'];
if ( empty( $field_data[ $field->id ] ) ) {
return esc_html__( 'No entries for this field', 'gravityforms' );
}
$field_results = '';
$field_type = GFFormsModel::get_input_type( $field );
switch ( $field_type ) {
case 'radio' :
case 'checkbox' :
case 'select' :
case 'rating' :
case 'multiselect' :
$results = $field_data[ $field->id ];
$non_zero_results = is_array( $results ) ? array_filter( $results ) : $results;
if ( empty( $non_zero_results ) ) {
$field_results .= esc_html__( 'No entries for this field', 'gravityforms' );
return $field_results;
}
$choices = $field->choices;
$data_table = array();
$data_table [] = array( esc_html__( 'Choice', 'gravityforms' ), esc_html__( 'Frequency', 'gravityforms' ) );
foreach ( $choices as $choice ) {
$text = $choice['text'];
$val = $results[ $choice['value'] ];
$data_table [] = array( $text, $val );
}
$bar_height = 40;
$chart_area_height = ( count( $choices ) * ( $bar_height + 20 ) );
$chart_options = array(
'isStacked' => true,
'height' => ( $chart_area_height + $bar_height ),
'fontSize' => 14,
'chartArea' => array(
'top' => 0,
'left' => 200,
'height' => $chart_area_height,
'width' => '100%',
),
'series' => array(
'0' => array(
'color' => 'silver',
'visibleInLegend' => 'false',
),
),
'hAxis' => array(
'viewWindowMode' => 'explicit',
'viewWindow' => array( 'min' => 0 ),
'title' => esc_html__( 'Frequency', 'gravityforms' ),
)
);
$data_table_json = htmlentities( json_encode( $data_table ), ENT_QUOTES, 'UTF-8', true );
$options_json = htmlentities( json_encode( $chart_options ), ENT_QUOTES, 'UTF-8', true );
$div_id = 'gresults-results-chart-field-' . $field->id;
$height = ''; // = sprintf("height:%dpx", (count($choices) * $bar_height));
$field_results .= sprintf( '<div class="gresults-chart-wrapper" style="width: 100%%;%s" id=%s data-datatable=\'%s\' data-options=\'%s\' data-charttype="bar" ></div>', $height, $div_id, $data_table_json, $options_json );
break;
case 'likert' :
$results = $field_data[ $field->id ];
$multiple_rows = $field->gsurveyLikertEnableMultipleRows ? true : false;
$scoring_enabled = $field->gsurveyLikertEnableScoring && class_exists( 'GFSurvey' ) ? true : false;
$n = 100;
$xr = 255;
$xg = 255;
$xb = 255;
$yr = 100;
$yg = 250;
$yb = 100;
$field_results .= "<div class='gsurvey-likert-field-results'>";
$field_results .= "<table class='gsurvey-likert'>";
$field_results .= '<tr>';
if ( $multiple_rows ) {
$field_results .= '<td></td>';
}
foreach ( $field->choices as $choice ) {
$field_results .= "<td class='gsurvey-likert-choice-label'>" . $choice['text'] . '</td>';
}
if ( $multiple_rows && $scoring_enabled ) {
$field_results .= sprintf( '<td>%s %s</td>', esc_html__( 'Average Score', 'gravityforms' ), gform_tooltip( 'gresults_average_row_score', null, true ) );
}
$field_results .= '</tr>';
foreach ( $field->gsurveyLikertRows as $row ) {
$row_text = $row['text'];
$row_value = $row['value'];
$max = 0;
foreach ( $field->choices as $choice ) {
if ( $multiple_rows ) {
$choice_value = rgar( $choice, 'value' );
$results_row = rgar( $results, $row_value );
$results_for_choice = rgar( $results_row, $choice_value );
$max = max( array( $max, $results_for_choice ) );
} else {
$max = max( array( $max, $results[ $choice['value'] ] ) );
}
}
$field_results .= '<tr>';
if ( $multiple_rows ) {
$field_results .= "<td class='gsurvey-likert-row-label'>" . $row_text . '</td>';
}
foreach ( $field->choices as $choice ) {
$val = $multiple_rows ? $results[ $row_value ][ $choice['value'] ] : $results[ $choice['value'] ];
$percent = $max > 0 ? round( $val / $max * 100, 0 ) : 0;
$red = (int) ( ( $xr + ( ( $percent * ( $yr - $xr ) ) / ( $n - 1 ) ) ) );
$green = (int) ( ( $xg + ( ( $percent * ( $yg - $xg ) ) / ( $n - 1 ) ) ) );
$blue = (int) ( ( $xb + ( ( $percent * ( $yb - $xb ) ) / ( $n - 1 ) ) ) );
$clr = 'rgb(' . $red . ',' . $green . ',' . $blue . ')';
$field_results .= "<td class='gsurvey-likert-results' style='background-color:{$clr}'>" . $val . '</td>';
}
if ( $multiple_rows && $scoring_enabled ) {
$row_sum = $results[ $row_value ]['row_score_sum'];
$average_row_score = $row_sum == 0 ? 0 : round( $row_sum / $entry_count, 3 );
$field_results .= "<td class='gsurvey-likert-results'>" . $average_row_score . '</td>';
}
$field_results .= '</tr>';
if ( false === $multiple_rows ) {
break;
}
}
$field_results .= '</table>';
$field_results .= '</div>';
if ( $scoring_enabled ) {
$sum = $results['sum_of_scores'];
$average_score = $sum == 0 ? 0 : round( $sum / $entry_count, 3 );
if ( $multiple_rows ) {
$average_global_score_tooltip = gform_tooltip( 'gresults_average_global_score', null, true );
$field_results .= sprintf( "<div class='gsurvey-likert-score'>%s %s: %s</div>", esc_html__( 'Average global score', 'gravityforms' ), $average_global_score_tooltip, $average_score );
} else {
$field_results .= sprintf( "<div class='gsurvey-likert-score'>%s %s: %s</div>", esc_html__( 'Average score', 'gravityforms' ), gform_tooltip( 'gresults_average_score', null, true ), $average_score );
}
}
break;
case 'rank' :
$results = $field_data[ $field->id ];
arsort( $results );
$field_results .= "<div class='gsurvey-rank-field-results'>";
$field_results .= ' <table>';
$field_results .= " <tr class='gresults-results-field-table-header'>";
$field_results .= " <td class='gresults-rank-field-label'>";
$field_results .= esc_html__( 'Item', 'gravityforms' );
$field_results .= ' </td>';
$field_results .= " <td class='gresults-rank-field-score'>";
$field_results .= esc_html__( 'Total Score', 'gravityforms' ) . '&nbsp;' . gform_tooltip( 'gresults_total_score', null, true );
$field_results .= ' </td>';
$field_results .= " <td class='gresults-rank-field-rank'>";
$field_results .= esc_html__( 'Aggregate Rank', 'gravityforms' ) . '&nbsp;' . gform_tooltip( 'gresults_agg_rank', null, true );
$field_results .= ' </td>';
$field_results .= ' </tr>';
$agg_rank = 1;
foreach ( $results as $choice_val => $score ) {
$field_results .= '<tr>';
$field_results .= " <td class='gresults-rank-field-label' style='text-align:left;'>";
$field_results .= RGFormsModel::get_choice_text( $field, $choice_val );
$field_results .= ' </td>';
$field_results .= " <td class='gresults-rank-field-score'>";
$field_results .= $score;
$field_results .= ' </td>';
$field_results .= " <td class='gresults-rank-field-rank'>";
$field_results .= $agg_rank;
$field_results .= ' </td>';
$field_results .= '</tr>';
$agg_rank ++;
}
$field_results .= '</table>';
$field_results .= '</div>';
break;
default :
$page_size = 5;
$offset = 0;
$field_id = $field->id;
$more_remaining = false;
$default_field_results = self::get_default_field_results( $form_id, $field, $search_criteria, $offset, $page_size, $more_remaining );
$field_results .= "<div class='gresults-results-field-sub-label'>" . esc_html__( 'Latest values:', 'gravityforms' ) . '</div>';
$field_results .= "<ul id='gresults-results-field-content-{$field_id}' class='gresults-results-field-content' data-offset='{$offset}'>";
$field_results .= $default_field_results;
$field_results .= '</ul>';
if ( $more_remaining ) {
$field_results .= "<a id='gresults-results-field-more-link-{$field_id}' class='gresults-results-field-more-link' href='javascript:void(0)' onclick='gresults.getMoreResults({$form_id},{$field_id})' onkeypress='gresults.getMoreResults({$form_id},{$field_id})'>" . esc_html__( 'Show more', 'gravityforms' ) . '</a>';
}
break;
}
return $field_results;
}
public function get_results_data( $form, $fields, $search_criteria = array(), $state_array = array(), $max_execution_time = 15 /* seconds */ ) {
// todo: add hooks to modify $max_execution_time and $page_size?
$page_size = 150;
$time_start = microtime( true );
$form_id = $form['id'];
$data = array();
$offset = 0;
$entry_count = 0;
$field_data = array();
if ( $state_array ) {
//get counts from state
$data = $state_array;
$offset = (int) rgar( $data, 'offset' );
unset( $data['offset'] );
$entry_count = $offset;
$field_data = rgar( $data, 'field_data' );
} else {
//initialize counts
foreach ( $fields as $field ) {
$field_type = GFFormsModel::get_input_type( $field );
if ( false === isset( $field->choices ) ) {
$field_data[ $field->id ] = 0;
continue;
}
$choices = $field->choices;
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableMultipleRows' ) ) {
foreach ( $field->gsurveyLikertRows as $row ) {
foreach ( $choices as $choice ) {
$field_data[ $field->id ][ $row['value'] ][ $choice['value'] ] = 0;
}
if ( rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
$field_data[ $field->id ][ $row['value'] ]['row_score_sum'] = 0;
}
}
} else {
if ( ! empty( $choices ) && is_array( $choices ) ) {
foreach ( $choices as $choice ) {
$field_data[ $field->id ][ $choice['value'] ] = 0;
}
} else {
$field_data[ $field->id ] = 0;
}
}
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
$field_data[ $field->id ]['sum_of_scores'] = 0;
}
}
}
$count_search_leads = GFAPI::count_entries( $form_id, $search_criteria );
$data['entry_count'] = $count_search_leads;
$entries_left = $count_search_leads - $offset;
while ( $entries_left > 0 ) {
$paging = array(
'offset' => $offset,
'page_size' => $page_size,
);
$search_leads_time_start = microtime( true );
$leads = GFFormsModel::search_leads( $form_id, $search_criteria, null, $paging );
$search_leads_time_end = microtime( true );
$search_leads_time = $search_leads_time_end - $search_leads_time_start;
$leads_in_search = count( $leads );
$entry_count += $leads_in_search;
$leads_processed = 0;
foreach ( $leads as $lead ) {
$lead_time_start = microtime( true );
foreach ( $fields as $field ) {
$field_type = GFFormsModel::get_input_type( $field );
$field_id = $field->id;
$value = RGFormsModel::get_lead_field_value( $lead, $field );
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableMultipleRows' ) ) {
if ( empty( $value ) ) {
continue;
}
foreach ( $value as $value_vector ) {
if ( empty( $value_vector ) ) {
continue;
}
list( $row_val, $col_val ) = explode( ':', $value_vector, 2 );
if ( isset( $field_data[ $field->id ][ $row_val ] ) && isset( $field_data[ $field->id ][ $row_val ][ $col_val ] ) ) {
$field_data[ $field->id ][ $row_val ][ $col_val ] ++;
if ( $field->gsurveyLikertEnableScoring ) {
$field_data[ $field->id ][ $row_val ]['row_score_sum'] += $this->get_likert_row_score( $row_val, $field, $lead );
}
}
}
} elseif ( $field_type == 'rank' ) {
$score = count( rgar( $field, 'choices' ) );
$values = explode( ',', $value );
foreach ( $values as $ranked_value ) {
$field_data[ $field->id ][ $ranked_value ] += $score;
$score --;
}
} else {
if ( empty( $field->choices ) ) {
if ( false === empty( $value ) ) {
$field_data[ $field_id ] ++;
}
continue;
}
$choices = $field->choices;
foreach ( $choices as $choice ) {
$choice_is_selected = false;
if ( is_array( $value ) ) {
$choice_value = rgar( $choice, 'value' );
if ( in_array( $choice_value, $value ) ) {
$choice_is_selected = true;
}
} else {
if ( RGFormsModel::choice_value_match( $field, $choice, $value ) ) {
$choice_is_selected = true;
}
}
if ( $choice_is_selected ) {
$field_data[ $field_id ][ $choice['value'] ] ++;
}
}
}
if ( $field_type == 'likert' && rgar( $field, 'gsurveyLikertEnableScoring' ) ) {
$field_data[ $field->id ]['sum_of_scores'] += $this->get_likert_score( $field, $lead );
}
}
$leads_processed ++;
$lead_time_end = microtime( true );
$total_execution_time = $lead_time_end - $search_leads_time_start;
$lead_execution_time = $lead_time_end - $lead_time_start;
if ( $total_execution_time + $lead_execution_time > $max_execution_time ) {
break;
}
}
$data['field_data'] = $field_data;
if ( isset( $this->_callbacks['calculation'] ) ) {
$data = call_user_func( $this->_callbacks['calculation'], $data, $form, $fields, $leads );
$field_data = $data['field_data'];
}
$offset += $leads_processed;
$entries_left -= $leads_processed;
$time_end = microtime( true );
$execution_time = ( $time_end - $time_start );
if ( $entries_left > 0 && $execution_time + $search_leads_time > $max_execution_time ) {
$data['status'] = 'incomplete';
$data['offset'] = $offset;
$progress = $data['entry_count'] > 0 ? round( $data['offset'] / $data['entry_count'] * 100 ) : 0;
$data['progress'] = $progress;
break;
}
if ( $entries_left <= 0 ) {
$data['status'] = 'complete';
}
}
$data['timestamp'] = time();
return $data;
}
public function get_likert_row_score( $row_val, $field, $entry ) {
return is_callable( array(
'GFSurvey',
'get_likert_row_score',
) ) ? GFSurvey::get_likert_row_score( $row_val, $field, $entry ) : 0;
}
public function get_likert_score( $field, $entry ) {
return is_callable( array(
'GFSurvey',
'get_field_score',
) ) ? GFSurvey::get_field_score( $field, $entry ) : 0;
}
public static function get_default_field_results( $form_id, $field, $search_criteria, &$offset, $page_size, &$more_remaining = false ) {
$field_results = '';
$sorting = array( 'key' => 'date_created', 'direction' => 'DESC' );
$c = 0;
do {
$paging = array( 'offset' => $offset, 'page_size' => $page_size );
$leads = GFFormsModel::search_leads( $form_id, $search_criteria, $sorting, $paging );
foreach ( $leads as $lead ) {
$value = RGFormsModel::get_lead_field_value( $lead, $field );
$content = apply_filters( 'gform_entries_field_value', $value, $form_id, $field->id, $lead );
if ( is_array( $content ) ) {
$content = join( ' ', $content );
}
if ( ! empty( $content ) ) {
$field_results .= "<li>" . wp_kses_post( $content ) . "</li>";
$c ++;
}
}
$offset += $page_size;
} while ( $c < $page_size && ! empty( $leads ) );
if ( ! empty( $leads ) ) {
$more_remaining = true;
}
return $field_results;
}
}
}

View File

@@ -0,0 +1,60 @@
.settings-field-map-table { }
.settings-field-map-table thead th { font-weight: bold; border-bottom: 1px solid #ccc; }
.settings-field-map-table tbody td { border-bottom: 1px dotted #eee; }
.settings-field-map-table select { max-width: 90%; }
.settings-field-map-table .custom-key-reset,
.settings-field-map-table .custom-value-reset,
.gaddon-setting-select-custom-container .select-custom-reset {
background: url( ../../../images/xit.gif ) no-repeat scroll 0 0 transparent;
cursor:pointer;
display:none;
position:absolute;
text-indent:-9999px;
width:10px;
height: 10px;
-moz-transition: none;
-webkit-transition: none;
-o-transition: color 0 ease-in;
transition: none;
}
.settings-field-map-table .custom-key-reset {
margin-top: 10px;
margin-left: 165px;
}
.settings-field-map-table .repeater th { padding-left: 0px; }
.settings-field-map-table .custom-key-reset:hover,
.settings-field-map-table .custom-value-reset:hover,
.gaddon-setting-select-custom-container .select-custom-reset:hover {
background-position-x: -10px;
}
.settings-field-map-table .custom-key-container:hover .custom-key-reset,
.settings-field-map-table .custom-key-container:hover .custom-value-reset,
.gaddon-setting-select-custom-container:hover .select-custom-reset {
display:block;
}
.gaddon-setting-select-custom-container { display:inline-block;position:relative; }
.gaddon-setting-select-custom-container .select-custom-reset {
left: 171px;
top: 10px;
}
.gaddon-section .required { color: #f00; }
.gaddon-setting-inline{
display:inline;
margin-right:6px;
}
.mt-gaddon-editor {
float: right;
position: relative;
right: 21px;
top: 70px;
}
.mt-gaddon-editor ~ .wp-editor-wrap {
margin-right: 23px;
}

View File

@@ -0,0 +1 @@
.settings-field-map-table thead th{font-weight:700;border-bottom:1px solid #ccc}.settings-field-map-table tbody td{border-bottom:1px dotted #eee}.settings-field-map-table select{max-width:90%}.gaddon-setting-select-custom-container .select-custom-reset,.settings-field-map-table .custom-key-reset,.settings-field-map-table .custom-value-reset{background:url(../../../images/xit.gif) no-repeat scroll 0 0 transparent;cursor:pointer;display:none;position:absolute;text-indent:-9999px;width:10px;height:10px;-moz-transition:none;-webkit-transition:none;-o-transition:color 0 ease-in;transition:none}.settings-field-map-table .custom-key-reset{margin-top:10px;margin-left:165px}.settings-field-map-table .repeater th{padding-left:0}.gaddon-setting-select-custom-container .select-custom-reset:hover,.settings-field-map-table .custom-key-reset:hover,.settings-field-map-table .custom-value-reset:hover{background-position-x:-10px}.gaddon-setting-select-custom-container:hover .select-custom-reset,.settings-field-map-table .custom-key-container:hover .custom-key-reset,.settings-field-map-table .custom-key-container:hover .custom-value-reset{display:block}.gaddon-setting-select-custom-container{display:inline-block;position:relative}.gaddon-setting-select-custom-container .select-custom-reset{left:171px;top:10px}.gaddon-section .required{color:red}.gaddon-setting-inline{display:inline;margin-right:6px}.mt-gaddon-editor{float:right;position:relative;right:21px;top:70px}.mt-gaddon-editor~.wp-editor-wrap{margin-right:23px}

View File

@@ -0,0 +1,292 @@
/* --------- TODO: remove quiz specific styles ------------------*/
table#gquiz-results-summary {
table-layout: fixed;
}
table#gquiz-results-summary td {
font-weight: bold;
text-align: center;
padding: 10px;
}
table#gquiz-results-summary td.gquiz-results-summary-label {
font-size: 1.2em;
}
table#gquiz-results-summary td.gquiz-results-summary-data {
font-size: 2em;
}
.gquiz-results-summary-data-box {
width: 75%;
padding: 15px 0;
min-width: 0;
margin: auto;
}
.gaddon-results-summary-secondary{
padding-top: 4px;
font-weight: normal;
font-size:13px;
}
.gaddon-results-summary-primary{
padding:5px;
}
.gquiz-field-precentages-correct {
float: left;
margin: 8px 0 0 64px;
}
/* -------------------------------------*/
table#gaddon-results-summary {
table-layout: fixed;
}
table#gaddon-results-summary td {
font-weight: bold;
text-align: center;
padding: 10px;
}
table#gaddon-results-summary td.gaddon-results-summary-label {
font-size: 1.2em;
}
table#gaddon-results-summary td.gaddon-results-summary-data {
font-size: 2em;
}
.gaddon-results-summary-data-box {
border: 1px solid silver;
padding: 10px;
width: 75%;
margin: auto;
}
.gaddon-field-precentages-correct {
float: left;
margin: 15px 0 0 50px;
}
/*-------------*/
#gresults-results {
margin-right: 300px;
}
.gform-admin .gresults-filter-loading .gform-spinner {
display: inline-block;
}
.gf-results .gf-result-box {
background: #fff;
border-radius: 3px;
border: 1px solid #e3e6ef;
box-shadow: 0 1px 4px rgb(18 25 97 / 8%);
padding: 1.562rem 1rem;
}
.gf-results .gf-result-box {
margin-right: 0;
margin-bottom: 1.25rem;
}
.gf-results .gf-result-box__primary {
display: flex;
}
@media screen and ( min-width: 782px ) {
.gf-results {
display: flex;
justify-content: space-between;
margin-bottom: 1.25rem;
}
.gf-results .gf-result-box {
flex: 1 1 0px;
margin-right: 1.25rem;
margin-bottom: 0;
}
.gf-results .gf-result-box:last-child {
margin-right: 0;
}
}
.gresults-results-field {
margin-bottom:20px;
}
.gresults-results-field table{
border-bottom: 1px solid silver;
border-spacing: 0;
}
.gresults-results-field table td{
padding:5px;
border-right: 1px solid silver;
border-top: 1px solid silver;
text-align:center;
}
.gresults-results-field-table-header{
background-color: #eeeeee;
}
.gresults-results-field table td:first-child {
border-left: 1px solid silver;
}
ul.gresults-results-field-content,
ul.gresults-results-field-content li{
list-style:disc outside none;
}
ul.gresults-results-field-content{
margin:10px;
}
td.gresults-rank-field-score,
td.gresults-rank-field-rank{
width:110px;
}
.gsurvey-rank-field-results table{
width:100%;
}
/* filter box */
#gresults-results-filter-content {
padding:12px;
border-top: 1px solid #EBEBF2
}
.gresults-results-filter-section-label {
font-size:1.2em;
font-weight:bold;
margin-top:10px;
margin-bottom:10px;
}
#gresults-results-filter label {
margin-top:10px;
display:block;
}
#gresults-results-filter-content #gform-no-filters {
color: #242748;
}
.gresults-remove,
.gresults-add {
margin-top:2px;
vertical-align:middle;
cursor:pointer;
}
.gresults-add {
margin-left:5px;
}
#gresults-no-filters{
color:silver;
}
.gresults-datepicker,
.gresults-filter-value,
.gresults-filter-field {
width:150px;
box-sizing:border-box;
-ms-box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
height: 2em;
padding: 2px;
}
.gresults-filter-operator {
width:70px;
}
#gresults-results-filter-buttons {
clear:both;
margin-top:20px;
width:180px;
}
.gresults-results-filter-field-label {
font-size:1.1em;
font-weight:bold;
margin-bottom:10px;
}
.gresults-results-filter-field {
margin-bottom:20px;
}
.gresults-results-filter-field ul li label {
margin-left:5px;
}
.gresults-results-filter-title {
font-size:1.5em;
font-weight:bold;
}
/*
#gresults-results-filter {
visibility: hidden;
}
*/
#gresults-results-field-filters-container.resizable {
border-bottom:5px double #ddd;
min-height:120px;
}
#gresults-results-field-filters {
height:100%;
overflow-y:auto;
}
.ui-resizable {
position:relative;
}
.ui-resizable-handle {
position:absolute;
font-size:0.1px;
z-index:99999;
display:block;
}
.ui-resizable-s {
cursor:s-resize;
height:7px;
width:100%;
bottom:-5px;
left:0px;
}
.gsurvey-likert-score{
margin-top:5px;
}
/* NEW */
#gquiz-results-summary { margin: 60px 0; }
.gresults-chart-wrapper { border-top: 1px solid #dfdfdf; margin: 0 0 28px; }
.gquiz-field-precentages-correct + .gresults-chart-wrapper { margin: 0 0 14px; }
.gresults-label-group { display: block; clear: right; }
.gresults-label-group .gresults-label { display: inline-block; width: 65px; }
.gresults-group-correct .gresults-value { color: green; }
.gresults-group-incorrect .gresults-value { color: red; }

View File

@@ -0,0 +1 @@
table#gquiz-results-summary{table-layout:fixed}table#gquiz-results-summary td{font-weight:700;text-align:center;padding:10px}table#gquiz-results-summary td.gquiz-results-summary-label{font-size:1.2em}table#gquiz-results-summary td.gquiz-results-summary-data{font-size:2em}.gquiz-results-summary-data-box{width:75%;padding:15px 0;min-width:0;margin:auto}.gaddon-results-summary-secondary{padding-top:4px;font-weight:400;font-size:13px}.gaddon-results-summary-primary{padding:5px}.gquiz-field-precentages-correct{float:left;margin:8px 0 0 64px}table#gaddon-results-summary{table-layout:fixed}table#gaddon-results-summary td{font-weight:700;text-align:center;padding:10px}table#gaddon-results-summary td.gaddon-results-summary-label{font-size:1.2em}table#gaddon-results-summary td.gaddon-results-summary-data{font-size:2em}.gaddon-results-summary-data-box{border:1px solid silver;padding:10px;width:75%;margin:auto}.gaddon-field-precentages-correct{float:left;margin:15px 0 0 50px}#gresults-results{margin-right:300px}.gform-admin .gresults-filter-loading .gform-spinner{display:inline-block}.gf-results .gf-result-box{background:#fff;border-radius:3px;border:1px solid #e3e6ef;box-shadow:0 1px 4px rgb(18 25 97 / 8%);padding:1.562rem 1rem}.gf-results .gf-result-box{margin-right:0;margin-bottom:1.25rem}.gf-results .gf-result-box__primary{display:flex}@media screen and (min-width:782px){.gf-results{display:flex;justify-content:space-between;margin-bottom:1.25rem}.gf-results .gf-result-box{flex:1 1 0px;margin-right:1.25rem;margin-bottom:0}.gf-results .gf-result-box:last-child{margin-right:0}}.gresults-results-field{margin-bottom:20px}.gresults-results-field table{border-bottom:1px solid silver;border-spacing:0}.gresults-results-field table td{padding:5px;border-right:1px solid silver;border-top:1px solid silver;text-align:center}.gresults-results-field-table-header{background-color:#eee}.gresults-results-field table td:first-child{border-left:1px solid silver}ul.gresults-results-field-content,ul.gresults-results-field-content li{list-style:disc outside none}ul.gresults-results-field-content{margin:10px}td.gresults-rank-field-rank,td.gresults-rank-field-score{width:110px}.gsurvey-rank-field-results table{width:100%}#gresults-results-filter-content{padding:12px;border-top:1px solid #ebebf2}.gresults-results-filter-section-label{font-size:1.2em;font-weight:700;margin-top:10px;margin-bottom:10px}#gresults-results-filter label{margin-top:10px;display:block}#gresults-results-filter-content #gform-no-filters{color:#242748}.gresults-add,.gresults-remove{margin-top:2px;vertical-align:middle;cursor:pointer}.gresults-add{margin-left:5px}#gresults-no-filters{color:silver}.gresults-datepicker,.gresults-filter-field,.gresults-filter-value{width:150px;box-sizing:border-box;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;height:2em;padding:2px}.gresults-filter-operator{width:70px}#gresults-results-filter-buttons{clear:both;margin-top:20px;width:180px}.gresults-results-filter-field-label{font-size:1.1em;font-weight:700;margin-bottom:10px}.gresults-results-filter-field{margin-bottom:20px}.gresults-results-filter-field ul li label{margin-left:5px}.gresults-results-filter-title{font-size:1.5em;font-weight:700}#gresults-results-field-filters-container.resizable{border-bottom:5px double #ddd;min-height:120px}#gresults-results-field-filters{height:100%;overflow-y:auto}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;z-index:99999;display:block}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.gsurvey-likert-score{margin-top:5px}#gquiz-results-summary{margin:60px 0}.gresults-chart-wrapper{border-top:1px solid #dfdfdf;margin:0 0 28px}.gquiz-field-precentages-correct+.gresults-chart-wrapper{margin:0 0 14px}.gresults-label-group{display:block;clear:right}.gresults-label-group .gresults-label{display:inline-block;width:65px}.gresults-group-correct .gresults-value{color:green}.gresults-group-incorrect .gresults-value{color:red}

View File

@@ -0,0 +1,308 @@
/* ------------------ Field Map ------------------ */
.gforms_form_settings.form-table .settings-field-map-table thead th {
font-weight: bold;
text-align: left;
padding-left:0px;
}
table.settings-field-map-table tbody td {
padding: 0px 0px 8px 0px;
}
.settings-field-map-table td:first-child {
width: 220px;
}
.settings-field-map-table td:last-child {
white-space: nowrap;
}
.settings-field-map-table .repeater th, .settings-field-map-table .repeater td:nth-child(2) {
padding-left: 0px;
padding-top: 0px;
width: 220px;
}
.settings-field-map-table select {
font-family: inherit;
height: 25px;
width: 210px;
}
.settings-field-map-table .chosen-container,
.settings-field-map-table .select2-container {
width: 210px !important;
}
.settings-field-map-table .custom-key-container,
.settings-field-map-table .custom-value-container {
position: relative;
width: 210px;
}
.settings-field-map-table .custom-key-container input,
.settings-field-map-table .custom-value-container input {
width: 210px;
}
.settings-field-map-table .custom-key-container input:not(:only-child),
.settings-field-map-table .custom-value-container input:not(:only-child) {
padding-right: 30px;
}
.settings-field-map-table .custom-key-container.supports-merge-tags input:not(:only-child),
.settings-field-map-table .custom-value-container.supports-merge-tags input:not(:only-child) {
padding-right: 50px;
}
.settings-field-map-table .custom-value-container.supports-merge-tags .all-merge-tags {
height: 25px;
position: absolute;
right: 36px;
top: 0;
}
.settings-field-map-table .custom-value-container.supports-merge-tags .all-merge-tags .tooltip-merge-tag {
background-position: center;
height: 25px;
margin: 0;
width: 25px;
}
.settings-field-map-table .custom-key-reset,
.settings-field-map-table .custom-value-reset {
background: url( '../images/field-map-reset.png' ) no-repeat center #ddd;
background-size: 10px 10px;
cursor: pointer;
display: inline-block;
height: 25px;
opacity: .3;
overflow: hidden;
position: absolute;
right: 11px;
text-indent: -9999px;
top: 0;
transition: opacity .25s ease-in-out;
width: 25px;
z-index: 2;
}
.settings-field-map-table .custom-key-reset:hover,
.settings-field-map-table .custom-value-reset:hover {
opacity: 1;
}
.settings-field-map-table .add-item span,
.settings-field-map-table .remove-item span {
background: url( '../images/field-map-buttons.png' ) no-repeat center top transparent;
background-size: 20px 100px;
cursor: pointer;
display: inline-block;
height: 25px;
overflow: hidden;
text-indent: -9999px;
width: 20px;
}
.settings-field-map-table .add-item span:hover {
background-position: 0 -25px;
}
.settings-field-map-table .remove-item span {
background-position: 0 -50px;
}
.settings-field-map-table .remove-item span:hover {
background-position: 0 -75px;
}
@media screen and ( max-width: 782px ) {
.settings-field-map-table .custom-key-container input:not(:only-child),
.settings-field-map-table .custom-value-container input:not(:only-child) {
padding-right: 45px;
}
.settings-field-map-table .custom-key-reset,
.settings-field-map-table .custom-value-reset {
height: 40px;
right: 0;
width: 40px;
}
}
/* ---------------- Select Custom ---------------- */
.gaddon-setting-select-custom-container .select-custom-reset {
background: url( ../../../images/xit.gif ) no-repeat scroll 0 0 transparent;
cursor:pointer;
display:none;
position:absolute;
text-indent:-9999px;
width:10px;
height: 10px;
-moz-transition: none;
-webkit-transition: none;
-o-transition: color 0 ease-in;
transition: none;
z-index: 99;
}
.gaddon-setting-select-custom-container .select-custom-reset:hover { background-position-x: -10px; }
.gaddon-setting-select-custom-container:hover .select-custom-reset {
display:block;
}
.gaddon-setting-select-custom-container {
display:inline-block;
position:relative;
width: 210px;
}
.gaddon-setting-select-custom-container .select-custom-reset {
left: 171px;
top: 10px;
}
.gaddon-section .required { color: #f00; }
.gaddon-setting-inline{
display:inline;
margin-right:6px;
}
.gaddon-section-description ol { }
.gaddon-section-description ol li {
list-style: decimal;
}
.repeater-buttons .add-item {
margin-right: 6px;
}
.add-item, .remove-item {
color: #444;
}
.mt-gaddon-editor {
float: right;
position: relative;
right: 0.625rem;
top: 2.8125rem;
z-index: 1;
}
div#tab_notification .mt-gaddon-editor {
top: 3.3125rem;
}
html[dir="rtl"] .mt-gaddon-editor {
float: left;
}
.mt-gaddon-editor ~ .wp-editor-wrap {
margin-right: 23px;
}
/* Visual Radio Buttons */
.gaddon-setting-choice-visual {
display: inline-block;
margin-bottom: 5px;
text-align: center;
}
.gaddon-setting-choice-visual label {
background: #F9F9F9;
border: 1px solid #eee;
display: inline-block;
}
.gaddon-setting-choice-visual label > span {
display: inline-block;
-webkit-filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
-moz-filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
filter: brightness( 1.8 ) grayscale( 1 ) opacity( .5 );
height: 65px;
min-width: 110px;
padding: 5px 10px 0;
-webkit-transition: all 100ms ease-in;
-moz-transition: all 100ms ease-in;
transition: all 100ms ease-in;
vertical-align: top;
}
.gaddon-setting-choice-visual label > span > i {
color: #0074a2;
display: inline-block;
font-size: 2.5em;
height: 32px;
margin: 5px;
width: 32px;
}
.gaddon-setting-choice-visual label > span > img{
height: 32px;
margin: 5px;
vertical-align: middle;
width: 32px;
}
.gaddon-setting-choice-visual input {
display: none;
}
.gaddon-setting-choice-visual input:checked + label {
background-color: #fff;
border: 1px solid #ccc;
}
.gaddon-setting-choice-visual input:checked + label > span {
-webkit-filter: none;
-moz-filter: none;
filter: none;
}
.gaddon-setting-choice-visual input:not([disabled]):not([checked]) + label > span:hover{
-webkit-filter: brightness(1.2) grayscale(.5) opacity(.9);
-moz-filter: brightness(1.2) grayscale(.5) opacity(.9);
filter: brightness(1.2) grayscale(.5) opacity(.9);
}
/* Feed Ordering */
.ui-sortable-helper {
background-color: #fff !important;
-webkit-box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
-moz-box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
box-shadow: 6px 6px 28px -9px rgba(0,0,0,0.75);
transform: rotate(1deg);
-moz-transform: rotate(1deg);
-webkit-transform: rotate(1deg);
}
.wp-list-table.feed-list-sortable .sort-column {
vertical-align: top;
width: 2.2em;
}
.wp-list-table.feed-list-sortable .feed-sort-handle {
cursor: move;
font-size: 1.25rem;
width: 2.2em;
}
/* ------------------ Feed List ------------------ */
@media screen and ( max-width: 782px ) {
.wp-list-table tbody tr:not(.inline-edit-row):not(.no-items) td:not(.column-primary)::before {
content: attr(data-colname) ":";
font-weight: bold;
}
.wp-list-table.feeds .manage-column {
vertical-align: top;
}
.wp-list-table.feeds .manage-column img {
margin-top: 16px;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

View File

@@ -0,0 +1,111 @@
var GFFeedOrder = function( args ) {
var self = this,
$ = jQuery;
/**
* Initialize Feed Ordering
*/
self.init = function() {
// Assign options to instance.
self.options = args;
// Prepare sorting handle.
var sortHandleMarkup = '<td class="sort-column"><i class="gform-icon gform-icon--drag-indicator feed-sort-handle"></i></td>';
// Add sorting handle to table.
$( '.wp-list-table thead tr, .wp-list-table tfoot tr' ).append( '<th class="sort-column"></th>' );
$( '.wp-list-table tbody tr' ).append( sortHandleMarkup );
// Initialize sorting.
self.initSorting();
};
/**
* Initialize jQuery UI Sortable.
*/
self.initSorting = function() {
$( '.wp-list-table tbody' ).sortable(
{
cursor: 'move',
handle: '.feed-sort-handle',
placeholder: 'feed-placeholder',
tolerance: 'pointer',
create: function() { $( '.wp-list-table' ).addClass( 'feed-list-sortable' ); },
helper: self.fixSortableColumnWidths,
start: self.setPlaceholderHeight,
update: self.updateFeedOrder,
}
);
}
/**
* Fix table column widths.
*/
self.fixSortableColumnWidths = function( event, tr ) {
var $originals = tr.children(),
$helper = tr.clone();
$helper.children().each( function( index ) {
$( this ).width( $originals.eq( index ).width() );
} );
return $helper;
}
/**
* Get order of feeds.
*/
self.getFeedOrder = function() {
// Get all the checkboxes from the feed list table.
var feed_checkboxes = $( '.wp-list-table tbody .check-column input[type="checkbox"]' );
// Map a function to the feed checkboxes array that returns the checkbox value.
return feed_checkboxes.map( function() {
return $( this ).val();
} ).get();
}
/**
* Set height of the placeholder draggable feed.
*/
self.setPlaceholderHeight = function( event, ui ) {
// Set the height of the placeholder to the height of the feed being moved.
$( '.wp-list-table .feed-placeholder' ).height( ui.item.height() );
}
/**
* Save the feed ordering to the database.
*/
self.updateFeedOrder = function( event, ui ) {
$.ajax(
ajaxurl,
{
method: 'POST',
dataType: 'JSON',
data: {
action: 'gf_save_feed_order',
addon: self.options.addon,
form_id: self.options.formId,
feed_order: self.getFeedOrder(),
nonce: self.options.nonce,
}
}
);
}
this.init();
}

View File

@@ -0,0 +1 @@
var GFFeedOrder=function(e){var o=this,i=jQuery;o.init=function(){o.options=e;i(".wp-list-table thead tr, .wp-list-table tfoot tr").append('<th class="sort-column"></th>'),i(".wp-list-table tbody tr").append('<td class="sort-column"><i class="gform-icon gform-icon--drag-indicator feed-sort-handle"></i></td>'),o.initSorting()},o.initSorting=function(){i(".wp-list-table tbody").sortable({cursor:"move",handle:".feed-sort-handle",placeholder:"feed-placeholder",tolerance:"pointer",create:function(){i(".wp-list-table").addClass("feed-list-sortable")},helper:o.fixSortableColumnWidths,start:o.setPlaceholderHeight,update:o.updateFeedOrder})},o.fixSortableColumnWidths=function(e,t){var o=t.children(),t=t.clone();return t.children().each(function(e){i(this).width(o.eq(e).width())}),t},o.getFeedOrder=function(){return i('.wp-list-table tbody .check-column input[type="checkbox"]').map(function(){return i(this).val()}).get()},o.setPlaceholderHeight=function(e,t){i(".wp-list-table .feed-placeholder").height(t.item.height())},o.updateFeedOrder=function(e,t){i.ajax(ajaxurl,{method:"POST",dataType:"JSON",data:{action:"gf_save_feed_order",addon:o.options.addon,form_id:o.options.formId,feed_order:o.getFeedOrder(),nonce:o.options.nonce}})},this.init()};

View File

@@ -0,0 +1,136 @@
var gfieldmap = function( options ) {
var self = this;
self.options = options;
self.UI = jQuery( '#gaddon-setting-row-'+ self.options.fieldName );
self.init = function() {
self.bindEvents();
self.setupData();
self.setupRepeater();
};
self.bindEvents = function() {
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]', function() {
var $select = jQuery( this ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
$input = $select.siblings( '.custom-key-container' );
if( $select.val() != 'gf_custom' ) {
return;
}
$selectElm.fadeOut( function() {
$input.fadeIn().focus();
} );
} );
self.UI.on( 'click', 'a.custom-key-reset', function( event ) {
event.preventDefault();
var $reset = jQuery( this ),
$input = $reset.parents( '.custom-key-container' ),
$select = $input.siblings( 'select.key' ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
$input.fadeOut( function() {
$input.find( 'input' ).val( '' ).change();
$select.val( '' ).trigger( 'change' );
$selectElm.fadeIn().focus();
} );
} );
self.UI.closest( 'form' ).on( 'submit', function( event ) {
jQuery( '[name^="_gaddon_setting_'+ self.options.fieldName +'_"]' ).each( function( i ) {
jQuery( this ).removeAttr( 'name' );
} );
} );
};
self.setupData = function() {
var data = jQuery( '#' + self.options.fieldId ).val();
self.data = data ? jQuery.parseJSON( data ) : null;
if ( ! self.data ) {
self.data = [ {
key: '',
value: '',
custom_key: ''
} ];
}
}
self.setupRepeater = function() {
var limit;
if (self.options.limit > 0){
limit = self.options.limit;
}
else{
limit = 0;
}
self.UI.find( 'tbody.repeater' ).repeater( {
limit: limit,
items: self.data,
addButtonMarkup: '<i class="gficon-add"></i>',
removeButtonMarkup: '<i class="gficon-subtract"></i>',
callbacks: {
add: function( obj, $elem, item ) {
var key_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]' );
if ( ! item.custom_key && key_select.length > 0 ) {
$elem.find( '.custom-key-container' ).hide();
} else {
$elem.find( '.key' ).hide();
}
gform.doAction( 'gform_fieldmap_add_row', obj, $elem, item );
},
save: function( obj, data ) {
data = jQuery.extend( {}, data );
for ( var i = 0; i < data.length; i++ ) {
if ( data[i].custom_key != '' ) {
data[i].custom = 1;
data[i].key = data[i].custom_key;
}
delete data[i].custom_key;
}
jQuery( '#'+ self.options.fieldId ).val( jQuery.toJSON( data ) );
}
}
} );
}
return self.init();
};

View File

@@ -0,0 +1 @@
var gfieldmap=function(e){var a=this;return a.options=e,a.UI=jQuery("#gaddon-setting-row-"+a.options.fieldName),a.init=function(){a.bindEvents(),a.setupData(),a.setupRepeater()},a.bindEvents=function(){a.UI.on("change",'select[name="_gaddon_setting_'+a.options.keyFieldName+'"]',function(){var e=jQuery(this),t=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,n=e.siblings(".custom-key-container");"gf_custom"==e.val()&&t.fadeOut(function(){n.fadeIn().focus()})}),a.UI.on("click","a.custom-key-reset",function(e){e.preventDefault();var t=jQuery(this).parents(".custom-key-container"),n=t.siblings("select.key"),i=n.data("chosen")?n.siblings(".chosen-container"):n.data("select2")?n.siblings(".select2-container"):n;t.fadeOut(function(){t.find("input").val("").change(),n.val("").trigger("change"),i.fadeIn().focus()})}),a.UI.closest("form").on("submit",function(e){jQuery('[name^="_gaddon_setting_'+a.options.fieldName+'_"]').each(function(e){jQuery(this).removeAttr("name")})})},a.setupData=function(){var e=jQuery("#"+a.options.fieldId).val();a.data=e?jQuery.parseJSON(e):null,a.data||(a.data=[{key:"",value:"",custom_key:""}])},a.setupRepeater=function(){var e=0<a.options.limit?a.options.limit:0;a.UI.find("tbody.repeater").repeater({limit:e,items:a.data,addButtonMarkup:'<i class="gficon-add"></i>',removeButtonMarkup:'<i class="gficon-subtract"></i>',callbacks:{add:function(e,t,n){var i=t.find('select[name="_gaddon_setting_'+a.options.keyFieldName+'"]');(!n.custom_key&&0<i.length?t.find(".custom-key-container"):t.find(".key")).hide(),gform.doAction("gform_fieldmap_add_row",e,t,n)},save:function(e,t){t=jQuery.extend({},t);for(var n=0;n<t.length;n++)""!=t[n].custom_key&&(t[n].custom=1,t[n].key=t[n].custom_key),delete t[n].custom_key;jQuery("#"+a.options.fieldId).val(jQuery.toJSON(t))}}})},a.init()};

View File

@@ -0,0 +1,234 @@
var GFFrontendFeeds = function( args ) {
var self = this,
$ = jQuery;
/**
* Initialize Feed Ordering
*/
self.init = function() {
// Assign options to instance.
self.options = args;
self.triggerInputIds = self.getTriggerInputIds( self.options.feeds );
self.activeFeeds = [];
self.evaluateFeeds();
self.bindEvents();
};
self.bindEvents = function() {
gform.addAction( 'gform_input_change', function( elem, formId, inputId ) {
var fieldId = parseInt( inputId ) + '';
var isTriggeredInput = $.inArray( inputId, self.triggerInputIds ) !== -1 || $.inArray( fieldId , self.triggerInputIds ) !== -1 ;
if( self.options.formId == formId && isTriggeredInput ) {
self.evaluateFeeds();
}
} );
};
self.evaluateFeeds = function() {
var feed, isMatch, isActivated;
for( i = 0; i < self.options.feeds.length; i++ ) {
feed = self.options.feeds[ i ];
isMatch = self.evaluateFeed( feed, self.options.formId );
isActivated = self.isFeedActivated( feed );
if( ! isMatch && isActivated !== null ) {
self.deactivateFeed( feed );
} else if( isMatch && ! isActivated && ( ! feed.isSingleFeed || ( feed.isSingleFeed && self.hasPriority( feed.feedId, feed.addonSlug ) ) ) ) {
self.activateFeed( feed );
}
}
/**
* Fires after the conditional logic on the form has been evaluated.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feeds_evaluated', self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_frontend_feeds_evaluated_{0}'.gformFormat( self.options.formId ), self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_{0}_frontend_feeds_evaluated'.gformFormat( feed.addonSlug ), self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_{0}_frontend_feeds_evaluated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), self.options.feeds, self.options.formId, self );
};
self.evaluateFeed = function( feed, formId ) {
// Feeds with no configured conditional logic always a match.
if( ! feed.conditionalLogic ) {
return true;
}
return gf_get_field_action( formId, feed.conditionalLogic ) == 'show';
};
self.getTriggerInputIds = function() {
var inputIds = [];
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( ! feed.conditionalLogic ) {
continue;
}
for( var j = 0; j < feed.conditionalLogic.rules.length; j++ ) {
var rule = self.options.feeds[i].conditionalLogic.rules[j];
if( $.inArray( rule.fieldId, inputIds ) == -1 ) {
inputIds.push( rule.fieldId );
}
}
}
return inputIds;
};
self.isFeedActivated = function( feed ) {
if( typeof feed != 'object' ) {
feed = self.getFeed( feed );
if( ! feed ) {
return false;
}
}
return typeof feed.isActivated != 'undefined' ? feed.isActivated : null;
};
self.getFeed = function( feedId ) {
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( feed.feedId == feedId ) {
return feed;
}
}
return false;
};
self.getFeedsByAddon = function( addonSlug, currentFeed, onlyActive ) {
var feeds = [];
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( feed.addonSlug == addonSlug
&& ! ( currentFeed && feed.feedId == currentFeed.feedId )
) {
if( onlyActive ) {
if( self.isFeedActivated( feed ) ) {
feeds.push( feed );
}
} else {
feeds.push( feed );
}
}
}
return feeds;
};
self.activateFeed = function( feeds ) {
if( feeds.feedId ) {
feeds = [ feeds ];
}
for( var i = 0; i < feeds.length; i++ ) {
var feed = feeds[ i ];
feed.isActivated = true;
/**
* Fires after the conditional logic on the form has been evaluated and the feed has been found to be active.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feed_activated', feed, self.options.formId );
gform.doAction( 'gform_frontend_feed_activated_{0}'.gformFormat( self.options.formId ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_activated'.gformFormat( feed.addonSlug ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_activated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), feed, self.options.formId );
if( feed.isSingleFeed ) {
self.deactivateFeed( self.getFeedsByAddon( feed.addonSlug, feed ) );
}
}
};
self.deactivateFeed = function( feeds ) {
if( feeds.feedId ) {
feeds = [ feeds ];
}
for( var i = 0; i < feeds.length; i++ ) {
var feed = feeds[ i ],
isActivated = self.isFeedActivated( feed );
if( isActivated === null || isActivated === false ) {
continue;
}
feed.isActivated = false;
/**
* Fires after the conditional logic on the form has been evaluated and the feed has become inactive.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feed_deactivated', feed, self.options.formId );
gform.doAction( 'gform_frontend_feed_deactivated_{0}'.gformFormat( self.options.formId ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_deactivated'.gformFormat( feed.addonSlug ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_deactivated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), feed, self.options.formId );
}
};
self.hasPriority = function( feedId, addonSlug ) {
var addonFeeds = self.getFeedsByAddon( addonSlug );
for( var i = 0; i <= addonFeeds.length; i++ ) {
var feed = addonFeeds[i];
if( feed.feedId != feedId && feed.isActivated ) {
return false;
} else if ( feed.feedId == feedId ) {
return true;
}
}
return false;
};
this.init();
};

View File

@@ -0,0 +1 @@
var GFFrontendFeeds=function(o){var r=this,f=jQuery;r.init=function(){r.options=o,r.triggerInputIds=r.getTriggerInputIds(r.options.feeds),r.activeFeeds=[],r.evaluateFeeds(),r.bindEvents()},r.bindEvents=function(){gform.addAction("gform_input_change",function(o,e,t){var d=parseInt(t)+"",t=-1!==f.inArray(t,r.triggerInputIds)||-1!==f.inArray(d,r.triggerInputIds);r.options.formId==e&&t&&r.evaluateFeeds()})},r.evaluateFeeds=function(){var o,e,t;for(i=0;i<r.options.feeds.length;i++)o=r.options.feeds[i],e=r.evaluateFeed(o,r.options.formId),t=r.isFeedActivated(o),e||null===t?e&&!t&&(!o.isSingleFeed||o.isSingleFeed&&r.hasPriority(o.feedId,o.addonSlug))&&r.activateFeed(o):r.deactivateFeed(o);gform.doAction("gform_frontend_feeds_evaluated",r.options.feeds,r.options.formId,r),gform.doAction("gform_frontend_feeds_evaluated_{0}".gformFormat(r.options.formId),r.options.feeds,r.options.formId,r),gform.doAction("gform_{0}_frontend_feeds_evaluated".gformFormat(o.addonSlug),r.options.feeds,r.options.formId,r),gform.doAction("gform_{0}_frontend_feeds_evaluated_{0}".gformFormat(o.addonSlug,r.options.formId),r.options.feeds,r.options.formId,r)},r.evaluateFeed=function(o,e){return!o.conditionalLogic||"show"==gf_get_field_action(e,o.conditionalLogic)},r.getTriggerInputIds=function(){for(var o=[],e=0;e<r.options.feeds.length;e++){var t=r.options.feeds[e];if(t.conditionalLogic)for(var d=0;d<t.conditionalLogic.rules.length;d++){var n=r.options.feeds[e].conditionalLogic.rules[d];-1==f.inArray(n.fieldId,o)&&o.push(n.fieldId)}}return o},r.isFeedActivated=function(o){return!("object"!=typeof o&&!(o=r.getFeed(o)))&&(void 0!==o.isActivated?o.isActivated:null)},r.getFeed=function(o){for(var e=0;e<r.options.feeds.length;e++){var t=r.options.feeds[e];if(t.feedId==o)return t}return!1},r.getFeedsByAddon=function(o,e,t){for(var d=[],n=0;n<r.options.feeds.length;n++){var i=r.options.feeds[n];i.addonSlug!=o||e&&i.feedId==e.feedId||t&&!r.isFeedActivated(i)||d.push(i)}return d},r.activateFeed=function(o){o.feedId&&(o=[o]);for(var e=0;e<o.length;e++){var t=o[e];t.isActivated=!0,gform.doAction("gform_frontend_feed_activated",t,r.options.formId),gform.doAction("gform_frontend_feed_activated_{0}".gformFormat(r.options.formId),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_activated".gformFormat(t.addonSlug),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_activated_{0}".gformFormat(t.addonSlug,r.options.formId),t,r.options.formId),t.isSingleFeed&&r.deactivateFeed(r.getFeedsByAddon(t.addonSlug,t))}},r.deactivateFeed=function(o){o.feedId&&(o=[o]);for(var e=0;e<o.length;e++){var t=o[e],d=r.isFeedActivated(t);null!==d&&!1!==d&&(t.isActivated=!1,gform.doAction("gform_frontend_feed_deactivated",t,r.options.formId),gform.doAction("gform_frontend_feed_deactivated_{0}".gformFormat(r.options.formId),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_deactivated".gformFormat(t.addonSlug),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_deactivated_{0}".gformFormat(t.addonSlug,r.options.formId),t,r.options.formId))}},r.hasPriority=function(o,e){for(var t=r.getFeedsByAddon(e),d=0;d<=t.length;d++){var n=t[d];if(n.feedId!=o&&n.isActivated)return!1;if(n.feedId==o)return!0}return!1},this.init()};

View File

@@ -0,0 +1,166 @@
var GFGenericMap = function( options ) {
var self = this;
self.options = options;
self.UI = jQuery( '#gaddon-setting-row-'+ self.options.fieldName );
self.init = function() {
self.bindEvents();
self.setupData();
self.setupRepeater();
};
self.bindEvents = function() {
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]', function() {
var $select = jQuery( this ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
$input = $select.siblings( '.custom-key-container' );
if( $select.val() != 'gf_custom' ) {
return;
}
$selectElm.fadeOut( function() {
$input.fadeIn().focus();
} );
} );
self.UI.on( 'change', 'select[name="_gaddon_setting_'+ self.options.valueFieldName +'"]', function() {
var $select = jQuery( this ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select ),
$input = $select.siblings( '.custom-value-container' );
if ( $select.val() != 'gf_custom' ) {
return;
}
$selectElm.fadeOut( function() {
$input.fadeIn().focus();
} );
} );
self.UI.on( 'click', 'a.custom-key-reset', function( event ) {
event.preventDefault();
var $reset = jQuery( this ),
$input = $reset.parents( '.custom-key-container' ),
$select = $input.siblings( 'select.key' ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
$input.fadeOut( function() {
$input.find( 'input' ).val( '' ).change();
$select.val( '' ).trigger( 'change' );
$selectElm.fadeIn().focus();
} );
} );
self.UI.on( 'click', 'a.custom-value-reset', function( event ) {
event.preventDefault();
var $reset = jQuery( this ),
$input = $reset.parents( '.custom-value-container' ),
$select = $input.siblings( 'select.value' ),
$selectElm = $select.data( 'chosen' ) ? $select.siblings( '.chosen-container' ) : ( $select.data( 'select2' ) ? $select.siblings( '.select2-container' ) : $select );
$input.fadeOut( function() {
$input.find( 'input' ).val( '' ).change();
$select.val( '' ).trigger( 'change' );
$selectElm.fadeIn().focus();
} );
} );
self.UI.closest( 'form' ).on( 'submit', function( event ) {
jQuery( '[name^="_gaddon_setting_'+ self.options.fieldName +'_"]' ).each( function( i ) {
jQuery( this ).removeAttr( 'name' );
} );
} );
};
self.setupData = function() {
var data = jQuery( '#' + self.options.fieldId ).val();
self.data = data ? jQuery.parseJSON( data ) : null;
if ( ! self.data ) {
self.data = [ {
key: '',
value: '',
custom_key: '',
custom_value: ''
} ];
}
}
self.setupRepeater = function() {
var limit = self.options.limit > 0 ? self.options.limit : 0;
self.UI.find( 'tbody.repeater' ).repeater( {
limit: limit,
items: self.data,
addButtonMarkup: '<i class="gficon-add"></i>',
removeButtonMarkup: '<i class="gficon-subtract"></i>',
callbacks: {
add: function( obj, $elem, item ) {
var key_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.keyFieldName +'"]' );
if ( ! item.custom_key && ( key_select.length > 0 && key_select.val() !== 'gf_custom' ) ) {
$elem.find( '.custom-key-container' ).hide();
} else {
$elem.find( '.key' ).hide();
}
var value_select = $elem.find( 'select[name="_gaddon_setting_'+ self.options.valueFieldName +'"]' );
if ( ! item.custom_value && ( value_select.length > 0 && value_select.val() !== 'gf_custom' ) ) {
$elem.find( '.custom-value-container' ).hide();
} else {
$elem.find( '.value' ).hide();
}
if ( self.options.mergeTags ) {
new gfMergeTagsObj( form, $elem.find( '.custom-value-container input' ) );
$elem.find( '.custom-value-container' ).addClass( 'supports-merge-tags' );
}
if ( window.hasOwnProperty( 'gform' ) ) {
gform.doAction( 'gform_fieldmap_add_row', obj, $elem, item );
}
},
save: function( obj, data ) {
jQuery( '#'+ self.options.fieldId ).val( JSON.stringify( data ) );
}
}
} );
}
return self.init();
};

View File

@@ -0,0 +1 @@
var GFGenericMap=function(e){var i=this;return i.options=e,i.UI=jQuery("#gaddon-setting-row-"+i.options.fieldName),i.init=function(){i.bindEvents(),i.setupData(),i.setupRepeater()},i.bindEvents=function(){i.UI.on("change",'select[name="_gaddon_setting_'+i.options.keyFieldName+'"]',function(){var e=jQuery(this),n=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,t=e.siblings(".custom-key-container");"gf_custom"==e.val()&&n.fadeOut(function(){t.fadeIn().focus()})}),i.UI.on("change",'select[name="_gaddon_setting_'+i.options.valueFieldName+'"]',function(){var e=jQuery(this),n=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,t=e.siblings(".custom-value-container");"gf_custom"==e.val()&&n.fadeOut(function(){t.fadeIn().focus()})}),i.UI.on("click","a.custom-key-reset",function(e){e.preventDefault();var n=jQuery(this).parents(".custom-key-container"),t=n.siblings("select.key"),a=t.data("chosen")?t.siblings(".chosen-container"):t.data("select2")?t.siblings(".select2-container"):t;n.fadeOut(function(){n.find("input").val("").change(),t.val("").trigger("change"),a.fadeIn().focus()})}),i.UI.on("click","a.custom-value-reset",function(e){e.preventDefault();var n=jQuery(this).parents(".custom-value-container"),t=n.siblings("select.value"),a=t.data("chosen")?t.siblings(".chosen-container"):t.data("select2")?t.siblings(".select2-container"):t;n.fadeOut(function(){n.find("input").val("").change(),t.val("").trigger("change"),a.fadeIn().focus()})}),i.UI.closest("form").on("submit",function(e){jQuery('[name^="_gaddon_setting_'+i.options.fieldName+'_"]').each(function(e){jQuery(this).removeAttr("name")})})},i.setupData=function(){var e=jQuery("#"+i.options.fieldId).val();i.data=e?jQuery.parseJSON(e):null,i.data||(i.data=[{key:"",value:"",custom_key:"",custom_value:""}])},i.setupRepeater=function(){var e=0<i.options.limit?i.options.limit:0;i.UI.find("tbody.repeater").repeater({limit:e,items:i.data,addButtonMarkup:'<i class="gficon-add"></i>',removeButtonMarkup:'<i class="gficon-subtract"></i>',callbacks:{add:function(e,n,t){var a=n.find('select[name="_gaddon_setting_'+i.options.keyFieldName+'"]'),a=((!t.custom_key&&0<a.length&&"gf_custom"!==a.val()?n.find(".custom-key-container"):n.find(".key")).hide(),n.find('select[name="_gaddon_setting_'+i.options.valueFieldName+'"]'));(!t.custom_value&&0<a.length&&"gf_custom"!==a.val()?n.find(".custom-value-container"):n.find(".value")).hide(),i.options.mergeTags&&(new gfMergeTagsObj(form,n.find(".custom-value-container input")),n.find(".custom-value-container").addClass("supports-merge-tags")),window.hasOwnProperty("gform")&&gform.doAction("gform_fieldmap_add_row",e,n,t)},save:function(e,n){jQuery("#"+i.options.fieldId).val(JSON.stringify(n))}}})},i.init()};

View File

@@ -0,0 +1,46 @@
function loadBillingLength(setting_name){
var intervals = window[setting_name + "_intervals"]
if(!intervals)
return;
var unit = jQuery("#" + setting_name + "_unit").val();
var min = gform.utils.escapeHtml( intervals[unit]["min"] );
var max = gform.utils.escapeHtml( intervals[unit]["max"] );
var lengthField = jQuery("#" + setting_name + "_length");
var length = lengthField.val();
var str = "";
for(var i=min; i<=max; i++){
var selected = length == i ? "selected='selected'" : "";
str += "<option value='" + i + "' " + selected + ">" + i + "</option>";
}
lengthField.html( str );
}
function cancel_subscription( entryId ) {
if ( !confirm( gaddon_payment_strings.subscriptionCancelWarning ) )
return;
jQuery( "#subscription_cancel_spinner" ).show();
jQuery( "#cancelsub" ).prop( "disabled", true );
jQuery.post(
ajaxurl,
{
action: "gaddon_cancel_subscription",
entry_id: entryId,
gaddon_cancel_subscription: gaddon_payment_strings.subscriptionCancelNonce
},
function ( response ) {
jQuery( "#subscription_cancel_spinner" ).hide();
if ( response.success === true ) {
jQuery( "#gform_payment_status" ).html( gform.utils.escapeHtml( gaddon_payment_strings.subscriptionCanceled ) );
jQuery( "#cancelsub" ).hide();
} else {
jQuery( "#cancelsub" ).prop( "disabled", false );
if ( response.success === false ) {
alert( gaddon_payment_strings.subscriptionError );
}
}
}
);
}

View File

@@ -0,0 +1 @@
function loadBillingLength(n){var e=window[n+"_intervals"];if(e){for(var s=jQuery("#"+n+"_unit").val(),i=gform.utils.escapeHtml(e[s].min),c=gform.utils.escapeHtml(e[s].max),e=jQuery("#"+n+"_length"),t=e.val(),r="",a=i;a<=c;a++)r+="<option value='"+a+"' "+(t==a?"selected='selected'":"")+">"+a+"</option>";e.html(r)}}function cancel_subscription(n){confirm(gaddon_payment_strings.subscriptionCancelWarning)&&(jQuery("#subscription_cancel_spinner").show(),jQuery("#cancelsub").prop("disabled",!0),jQuery.post(ajaxurl,{action:"gaddon_cancel_subscription",entry_id:n,gaddon_cancel_subscription:gaddon_payment_strings.subscriptionCancelNonce},function(n){jQuery("#subscription_cancel_spinner").hide(),!0===n.success?(jQuery("#gform_payment_status").html(gform.utils.escapeHtml(gaddon_payment_strings.subscriptionCanceled)),jQuery("#cancelsub").hide()):(jQuery("#cancelsub").prop("disabled",!1),!1===n.success&&alert(gaddon_payment_strings.subscriptionError))}))}

View File

@@ -0,0 +1,251 @@
var gresultsAjaxRequest;
var gresults = {
drawCharts: function () {
var containers = jQuery('.gresults-chart-wrapper');
containers.each(function (index, elem) {
var id = jQuery(elem).attr('id');
var options = jQuery(elem).data('options');
var datatable = jQuery(elem).data('datatable');
var chartType = jQuery(elem).data('charttype');
var data_array = datatable;
var data = google.visualization.arrayToDataTable(data_array);
var cont = document.getElementById(id);
var chart;
if (chartType == "bar") {
chart = new google.visualization.BarChart(cont);
} else if (chartType == "pie") {
chart = new google.visualization.PieChart(cont);
} else if (chartType == "column") {
chart = new google.visualization.ColumnChart(cont);
}
chart.draw(data, options);
});
},
renderStateData: function (state) {
var results = jQuery("#gresults-results");
results.data('searchcriteria', state.searchCriteria);
jQuery("#gresults-results-filter").html(state.filterUI);
results.css('opacity', 0);
results.html(state.html);
gresults.drawCharts();
results.fadeTo("slow", 1);
var filterContainer = jQuery("#gresults-results-field-filters-container");
filterContainer.resizable();
filterContainer.resizable('destroy');
filterContainer.resizable({
handles: 's'
});
},
getResults: function () {
gresults.recordFormState();
var gresultsData = jQuery('#gresults-results-filter-form').serialize();
gresults.sendRequest(gresultsData)
},
sendRequest: function (gresultsData, serverStateObject, checkSum) {
var results = jQuery("#gresults-results");
var filterButtons = jQuery("#gresults-results-filter-buttons input");
var viewSlug = jQuery("#gresults-view-slug").val();
var nonce = jQuery("#_gf_results_nonce").val()
var data_str = "action=gresults_get_results_" + viewSlug + "&" + gresultsData + '&_gf_results_nonce' + nonce ;
if (serverStateObject)
data_str += "&state=" + serverStateObject + "&checkSum=" + checkSum;
gresultsAjaxRequest = jQuery.ajax({
url : ajaxurl,
type : 'POST',
dataType : 'json',
data : data_str,
beforeSend: function (xhr, opts) {
results.fadeTo("slow", 0.33);
results.html('');
gform.utils.trigger( { event: 'gform/page_loader/show' } );
filterButtons.attr('disabled', 'disabled');
}
})
.done(function (response) {
if (!response || response === -1) {
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
results.html(gresultsStrings.ajaxError);
} else {
if (response.status === "complete") {
filterButtons.removeAttr('disabled');
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
results.html(response.html);
jQuery("#gresults-results").data('searchcriteria', response.searchCriteria); //used in 'more' links
var filterUI = jQuery("#gresults-results-filter").html();
gresults.drawCharts();
results.fadeTo("slow", 1);
if (window.history.replaceState) {
if (!history.state) {
history.replaceState({"html": response.html, "filterUI": filterUI, "searchCriteria": response.searchCriteria}, "", "?" + gresultsData);
} else {
history.pushState({"html": response.html, "filterUI": filterUI, "searchCriteria": response.searchCriteria}, "", "?" + gresultsData);
}
}
gresults.drawCharts();
if (window["gform_initialize_tooltips"])
gform_initialize_tooltips();
} else if (response.status === "incomplete") {
serverStateObject = response.stateObject;
gresults.sendRequest(gresultsData, serverStateObject, response.checkSum);
results.html(response.html);
} else {
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
results.html(gresultsStrings.ajaxError);
}
}
})
.fail(function (error) {
filterButtons.removeAttr('disabled');
results.fadeTo("fast", 1);
var msg = error.statusText;
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
if (msg == "abort") {
msg = "Request cancelled";
} else {
msg = gresultsStrings.ajaxError;
}
results.html(msg);
})
},
getMoreResults: function (formId, fieldId) {
var container = jQuery('#gresults-results-field-content-' + fieldId),
results = jQuery("#gresults-results"),
offset = jQuery(container).data('offset'),
viewSlug = jQuery("#gresults-view-slug").val(),
searchCriteria = results.data('searchcriteria'),
nonce = jQuery("#_gf_results_nonce").val();
jQuery.ajax({
url : ajaxurl,
type : 'POST',
dataType: 'json',
data : {
action: 'gresults_get_more_results_' + viewSlug,
view: viewSlug,
form_id: formId,
field_id: fieldId,
offset: offset,
search_criteria: searchCriteria,
_gf_results_nonce: nonce
},
success : function (response) {
if (response === -1) {
//permission denied
}
else {
if (response.html)
jQuery(container).append(response.html);
if (!response.more_remaining)
jQuery('#gresults-results-field-more-link-' + fieldId).hide();
jQuery(container).data('offset', response.offset);
}
}
});
return false;
},
clearFilterForm: function () {
jQuery("#gresults-results-field-filters-container").off('click', '.gform-add').gfFilterUI(gresultsFilterSettings, [], true);
jQuery('#gresults-results-filter-form').find('input, select').each(function () {
switch (this.type) {
case 'text':
case 'select-one':
jQuery(this).val('').change();
break;
case 'checkbox':
case 'radio':
this.checked = false;
}
});
},
recordFormState: function () {
jQuery("#gresults-results-filter-form input[type='radio']").each(function () {
if (this.checked) {
jQuery(this).prop("defaultChecked", true);
} else {
jQuery(this).prop("defaultChecked", false);
}
});
jQuery("#gresults-results-filter-form input[type='checkbox']").each(function () {
if (this.checked) {
jQuery(this).prop("defaultChecked", true);
} else {
jQuery(this).prop("defaultChecked", false);
}
});
jQuery("#gresults-results-filter-form input[type='text']").each(function () {
jQuery(this).prop("defaultValue", jQuery(this).val());
});
jQuery("#gresults-results-filter-form select option").each(function () {
jQuery(this).prop("defaultSelected", jQuery(this).prop('selected'));
});
},
setCustomFilter: function(key, value){
elementId = "gresults-custom-" + key;
if(jQuery('#' + elementId).length == 0)
jQuery('#gresults-results-filter-form').append("<input type='hidden' id='" + elementId + "' name='" + key + "' value='" + value + "'>");
else
jQuery('#' + elementId).val(value);
}
};
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(gresults.drawCharts);
jQuery( window ).on( 'load', function () {
if (jQuery("#gresults-results").length > 0) {
jQuery("#gresults-results-field-filters-container").gfFilterUI(gresultsFilterSettings, gresultsInitVars, true);
var $window = jQuery(window);
$window.resize(function (e) {
if (e.target === window) {
gresults.drawCharts();
}
});
window.onpopstate = function (e) {
if (e.state)
gresults.renderStateData(e.state)
};
jQuery("#gresults-results-filter-date-start, #gresults-results-filter-date-end").datepicker({dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true});
jQuery('.ui-datepicker-trigger').on('click', function() {
jQuery(this).parent().find('input').datepicker( 'show' );
});
jQuery("#gresults-results-filter-form").submit(function (e) {
gresults.getResults();
return false;
});
if (history.state) {
gresults.renderStateData(history.state)
} else {
gresults.getResults();
}
if (window["gform_initialize_tooltips"])
gform_initialize_tooltips();
}
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,131 @@
window.GFToken = null;
( function( $ ) {
GFToken = function( args ) {
for ( var prop in args ) {
if ( args.hasOwnProperty( prop ) )
this[prop] = args[prop];
}
this.form = $( '#gform_' + this.formId );
this.init = function() {
var GFTokenObj = this;
this.tokens = {};
/* Initialize spinner. */
if ( ! this.isAjax )
gformInitSpinner( this.formId );
/* If multipage form, run on gform_page_loaded. */
if ( this.hasPages ) {
$( document ).bind( 'gform_page_loaded', function( event, form_id, current_page ) {
if ( form_id != GFTokenObj.formId)
return;
if ( current_page != GFTokenObj.pageCount)
GFTokenObj.saveEntryData();
} );
}
this.form.submit( function() {
GFTokenObj.onSubmit();
} );
};
this.onSubmit = function() {
if ( this.form.data('gftokensubmitting') ) {
return;
} else {
event.preventDefault();
this.form.data( 'gftokensubmitting', true );
}
this.saveEntryData();
this.processTokens();
}
this.processTokens = function() {
/* Process feeds. */
for ( var feed_id in this.feeds ) {
this.active_feed = this.feeds[feed_id];
/* Create new feed object so we can store the billing information. */
var feed = {
'billing_fields': {},
'id': this.active_feed.id,
'name': this.active_feed.name
};
/* Add billing information to feed object. */
for ( var billing_field in this.active_feed.billing_fields ) {
field_id = this.active_feed.billing_fields[ billing_field ];
feed.billing_fields[ billing_field ] = this.entry_data[ field_id ];
}
/* Get credit card token response. */
window[ this.callback ].createToken( feed, this );
}
}
this.saveEntryData = function() {
var GFPaymentObj = this,
input_prefix = 'input_' + this.formId + '_';
if ( ! this.entry_data )
this.entry_data = {};
this.form.find( 'input[id^="' + input_prefix + '"], select[id^="' + input_prefix + '"], textarea[id^="' + input_prefix + '"]' ).each( function() {
var input_id = $( this ).attr( 'id' ).replace( input_prefix, '' ).replace( '_', '.' );
if ( $.inArray( input_id, GFPaymentObj.fields ) >= 0 )
GFPaymentObj.entry_data[ input_id ] = $( this ).val();
} );
}
this.saveToken = function( token ) {
/* Add token response to tokens array. */
this.tokens[ this.active_feed.id ] = {
'feed_id': this.active_feed.id,
'response': token
};
if ( this.tokens.length == this.feeds.length ) {
/* Add tokens to form. */
this.form.find( this.responseField ).val( $.toJSON( this.tokens ) );
/* Submit the form. */
this.form.submit();
}
}
this.init();
}
} )( jQuery );

View File

@@ -0,0 +1 @@
window.GFToken=null,function(n){GFToken=function(i){for(var t in i)i.hasOwnProperty(t)&&(this[t]=i[t]);this.form=n("#gform_"+this.formId),this.init=function(){var s=this;this.tokens={},this.isAjax||gformInitSpinner(this.formId),this.hasPages&&n(document).bind("gform_page_loaded",function(i,t,e){t==s.formId&&e!=s.pageCount&&s.saveEntryData()}),this.form.submit(function(){s.onSubmit()})},this.onSubmit=function(){this.form.data("gftokensubmitting")||(event.preventDefault(),this.form.data("gftokensubmitting",!0),this.saveEntryData(),this.processTokens())},this.processTokens=function(){for(var i in this.feeds){this.active_feed=this.feeds[i];var t,e={billing_fields:{},id:this.active_feed.id,name:this.active_feed.name};for(t in this.active_feed.billing_fields)field_id=this.active_feed.billing_fields[t],e.billing_fields[t]=this.entry_data[field_id];window[this.callback].createToken(e,this)}},this.saveEntryData=function(){var t=this,e="input_"+this.formId+"_";this.entry_data||(this.entry_data={}),this.form.find('input[id^="'+e+'"], select[id^="'+e+'"], textarea[id^="'+e+'"]').each(function(){var i=n(this).attr("id").replace(e,"").replace("_",".");0<=n.inArray(i,t.fields)&&(t.entry_data[i]=n(this).val())})},this.saveToken=function(i){this.tokens[this.active_feed.id]={feed_id:this.active_feed.id,response:i},this.tokens.length==this.feeds.length&&(this.form.find(this.responseField).val(n.toJSON(this.tokens)),this.form.submit())},this.init()}}(jQuery);

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

View File

@@ -0,0 +1,329 @@
/**
* jQuery Repeater
*
* Easily create a section of repeatable items.
*
* 1. Include repeater.js
* 2. Define a template to be used by the repeater.
* a. Input elements should have a class "property_{i}" (do not replace {i} with an index, the script will handle this.
* b. The template should include a container for the "row" of elements.
* c. Use the {buttons} merge tag to indicate the location of the repeater buttons.
*
* Example:
* <div class="repeater">
* <!-- Template Start -->
* <div class="row">
* <input class="name_{i}" />
* <input class="age_{i}" />
* {buttons}
* </div>
* <!-- / Template Ends -->
* </div>
*
* 3. Define a "save" callback to handle how your data is saved. It will give you an array of objects representing your data.
*
*/
jQuery.fn.repeater = function( options ) {
var self = this,
defaults = {
template: '',
limit: 5,
items: [{}],
saveEvents: 'blur change',
saveElements: 'input, select',
addButtonMarkup: '+',
removeButtonMarkup: '-',
minItemCount: 1,
callbacks: {
save: function() { },
beforeAdd: function() { },
add: function() { },
beforeAddNew: function() { },
addNew: function() { },
beforeRemove: function() { },
remove: function() { },
repeaterButtons: function() { return false; }
}
};
self.options = jQuery.extend( true, {}, defaults, options );
self.elem = jQuery( this );
self.items = self.options.items;
self.callbacks = self.options.callbacks;
self._template = self.options.template;
self._baseObj = self.items[0];
self.init = function() {
self.stashTemplate();
self.elem.addClass( 'repeater' );
self.refresh();
self.bindEvents();
return self;
}
self.bindEvents = function() {
self.options.saveEvents = self.getNamespacedEvents( self.options.saveEvents );
self.elem.off( 'click.repeater', 'a.add-item' );
self.elem.on( 'click.repeater', 'a.add-item:not(.inactive)', function() {
self.addNewItem( this );
});
self.elem.off( 'click.repeater', 'a.remove-item' );
self.elem.on( 'click.repeater', 'a.remove-item', function( event ){
self.removeItem( this );
});
self.elem.off( self.options.saveEvents, self.options.saveElements );
self.elem.on( self.options.saveEvents, self.options.saveElements, function() {
self.save();
});
}
self.stashTemplate = function() {
// if no template provided or in "storage", use current HTML
if( ! self._template )
self._template = self.elem.html();
self._template = jQuery.trim( self._template );
}
self.addItem = function( item, index ) {
var itemMarkup = self.getItemMarkup( item, index),
itemElem = jQuery( itemMarkup ).addClass( 'item-' + index );
self.callbacks.beforeAdd( self, itemElem, item, index );
self.append( itemElem );
self.populateSelects( item, index );
self.callbacks.add( self, itemElem, item, index );
}
self.getItemMarkup = function( item, index ) {
var itemMarkup = self._template;
for( var property in item ) {
if( ! item.hasOwnProperty( property ) )
continue;
itemMarkup = itemMarkup.replace( /{i}/g, index );
itemMarkup = itemMarkup.replace( '{buttons}', self.getRepeaterButtonsMarkup( index ) );
itemMarkup = itemMarkup.replace( new RegExp( '{' + property + '}', 'g' ), escapeAttr( item[property] ) );
}
return itemMarkup;
}
self.getRepeaterButtonsMarkup = function( index ) {
var buttonsMarkup = self.callbacks.repeaterButtons( self, index );
if( ! buttonsMarkup )
buttonsMarkup = self.getDefaultButtonsMarkup( index );
return buttonsMarkup;
}
self.getDefaultButtonsMarkup = function( index ) {
var cssClass = self.items.length >= self.options.limit && self.options.limit !== 0 ? 'inactive' : '',
buttons = '<a class="add-item ' + cssClass + '" data-index="' + index + '">' + self.options.addButtonMarkup + '</a>';
if( self.items.length > self.options.minItemCount )
buttons += '<a class="remove-item" data-index="' + index + '">' + self.options.removeButtonMarkup + '</a>';
return '<div class="repeater-buttons">' + buttons + '</div>';
}
self.populateSelects = function( item, index ) {
// after appending the row, check each property to see if it is a select and then populate
for ( var property in item ) {
if ( ! item.hasOwnProperty( property ) ) {
continue;
}
var input = self.elem.find( '.' + property + '_' + index );
if ( ! input.is( 'select' ) ) {
continue;
}
if ( jQuery.isArray( item[ property ] ) ) {
input.val( item[ property ] );
} else {
input.find( 'option[value="' + item[ property ] + '"]' ).prop( 'selected', true );
}
}
}
self.addNewItem = function( elemOrItem, index ) {
var isElem = self.isElement( elemOrItem ),
index = parseInt( typeof index !== 'undefined' ? index : ( isElem ? parseInt( jQuery( elemOrItem ).attr( 'data-index' ), 10 ) + 1 : self.items.length ), 10 ),
item = isElem ? self.getBaseObject() : elemOrItem;
self.callbacks.beforeAddNew( self, index );
self.items.splice( index, 0, item );
self.callbacks.addNew( self, index );
self.refresh().save();
return self;
}
self.removeItem = function( elemOrIndex ) {
var index = self.isElement( elemOrIndex ) ? jQuery( elemOrIndex ).attr( 'data-index' ) : elemOrIndex;
self.callbacks.beforeRemove( self, index );
// using delete (over splice) to maintain the correct indexes for
// the items array when saving the data from the UI
delete self.items[index];
self.callbacks.remove( self, index );
self.save().refresh();
}
self.refresh = function() {
self.elem.empty();
for( var i = 0; i < self.items.length; i++ ) {
self.addItem( self.items[i], i );
}
return self;
}
self.save = function() {
var keys = self.getBaseObjectKeys(),
data = [];
for( var i = 0; i < self.items.length; i++ ) {
if( typeof self.items[i] == 'undefined' )
continue;
var item = {};
for( var j = 0; j < keys.length; j++ ) {
var key = keys[j],
id = '.' + key + '_' + i,
value = self.elem.find( id ).val();
item[key] = typeof value == 'undefined' ? false : value;
}
data.push( item );
}
// save data to items
self.items = data;
// save data externally via callback
self.callbacks.save( self, data );
return self;
}
/**
* Loops through the current items array and retrieves the object properties of the
* first valid item object. Originally this would simply pull the object keys from
* the first index of the items array; however, when the first item has been
* 'deleted' (see the save() method), it will be undefined.
*/
self.getBaseObjectKeys = function() {
var keys = [],
items = self.items.length > 0 ? self.items : [ self._baseObj ];
for( var i = 0; i < items.length; i++ ) {
if( typeof items[i] == 'undefined' )
continue;
for( var key in items[i] ) {
if( ! items[i].hasOwnProperty( key ) )
continue;
keys.push( key );
}
break;
}
return keys;
}
self.getBaseObject = function() {
var item = {},
keys = self.getBaseObjectKeys();
for( var i = 0; i < keys.length; i++ ) {
item[keys[i]] = '';
}
return item;
}
self.getNamespacedEvents = function( events ) {
var events = events.split( ' ' ),
namespacedEvents = [];
for( var i = 0; i < events.length; i++ ) {
namespacedEvents.push( events[i] + '.repeater' );
}
return namespacedEvents.join( ' ' );
}
/**
* http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
* @param obj
* @returns {boolean}
*/
self.isElement = function( obj ) {
try {
//Using W3 DOM2 (works for FF, Opera and Chrom)
return obj instanceof HTMLElement;
}
catch(e){
//Browsers not supporting W3 DOM2 don't have HTMLElement and
//an exception is thrown and we end up here. Testing some
//properties that all elements have. (works on IE7)
return (typeof obj==="object") &&
(obj.nodeType===1) && (typeof obj.style === "object") &&
(typeof obj.ownerDocument ==="object");
}
}
return self.init();
};

View File

@@ -0,0 +1 @@
jQuery.fn.repeater=function(e){var i=this;return i.options=jQuery.extend(!0,{},{template:"",limit:5,items:[{}],saveEvents:"blur change",saveElements:"input, select",addButtonMarkup:"+",removeButtonMarkup:"-",minItemCount:1,callbacks:{save:function(){},beforeAdd:function(){},add:function(){},beforeAddNew:function(){},addNew:function(){},beforeRemove:function(){},remove:function(){},repeaterButtons:function(){return!1}}},e),i.elem=jQuery(this),i.items=i.options.items,i.callbacks=i.options.callbacks,i._template=i.options.template,i._baseObj=i.items[0],i.init=function(){return i.stashTemplate(),i.elem.addClass("repeater"),i.refresh(),i.bindEvents(),i},i.bindEvents=function(){i.options.saveEvents=i.getNamespacedEvents(i.options.saveEvents),i.elem.off("click.repeater","a.add-item"),i.elem.on("click.repeater","a.add-item:not(.inactive)",function(){i.addNewItem(this)}),i.elem.off("click.repeater","a.remove-item"),i.elem.on("click.repeater","a.remove-item",function(e){i.removeItem(this)}),i.elem.off(i.options.saveEvents,i.options.saveElements),i.elem.on(i.options.saveEvents,i.options.saveElements,function(){i.save()})},i.stashTemplate=function(){i._template||(i._template=i.elem.html()),i._template=jQuery.trim(i._template)},i.addItem=function(e,t){var n=i.getItemMarkup(e,t),n=jQuery(n).addClass("item-"+t);i.callbacks.beforeAdd(i,n,e,t),i.append(n),i.populateSelects(e,t),i.callbacks.add(i,n,e,t)},i.getItemMarkup=function(e,t){var n,a=i._template;for(n in e)e.hasOwnProperty(n)&&(a=(a=(a=a.replace(/{i}/g,t)).replace("{buttons}",i.getRepeaterButtonsMarkup(t))).replace(new RegExp("{"+n+"}","g"),escapeAttr(e[n])));return a},i.getRepeaterButtonsMarkup=function(e){return i.callbacks.repeaterButtons(i,e)||i.getDefaultButtonsMarkup(e)},i.getDefaultButtonsMarkup=function(e){var t='<a class="add-item '+(i.items.length>=i.options.limit&&0!==i.options.limit?"inactive":"")+'" data-index="'+e+'">'+i.options.addButtonMarkup+"</a>";return i.items.length>i.options.minItemCount&&(t+='<a class="remove-item" data-index="'+e+'">'+i.options.removeButtonMarkup+"</a>"),'<div class="repeater-buttons">'+t+"</div>"},i.populateSelects=function(e,t){for(var n in e){var a;e.hasOwnProperty(n)&&(a=i.elem.find("."+n+"_"+t)).is("select")&&(jQuery.isArray(e[n])?a.val(e[n]):a.find('option[value="'+e[n]+'"]').prop("selected",!0))}},i.addNewItem=function(e,t){var n=i.isElement(e),t=parseInt(void 0!==t?t:n?parseInt(jQuery(e).attr("data-index"),10)+1:i.items.length,10),n=n?i.getBaseObject():e;return i.callbacks.beforeAddNew(i,t),i.items.splice(t,0,n),i.callbacks.addNew(i,t),i.refresh().save(),i},i.removeItem=function(e){e=i.isElement(e)?jQuery(e).attr("data-index"):e;i.callbacks.beforeRemove(i,e),delete i.items[e],i.callbacks.remove(i,e),i.save().refresh()},i.refresh=function(){i.elem.empty();for(var e=0;e<i.items.length;e++)i.addItem(i.items[e],e);return i},i.save=function(){for(var e=i.getBaseObjectKeys(),t=[],n=0;n<i.items.length;n++)if(void 0!==i.items[n]){for(var a={},r=0;r<e.length;r++){var s=e[r],o=i.elem.find("."+s+"_"+n).val();a[s]=void 0!==o&&o}t.push(a)}return i.items=t,i.callbacks.save(i,t),i},i.getBaseObjectKeys=function(){for(var e=[],t=0<i.items.length?i.items:[i._baseObj],n=0;n<t.length;n++)if(void 0!==t[n]){for(var a in t[n])t[n].hasOwnProperty(a)&&e.push(a);break}return e},i.getBaseObject=function(){for(var e={},t=i.getBaseObjectKeys(),n=0;n<t.length;n++)e[t[n]]="";return e},i.getNamespacedEvents=function(e){for(var e=e.split(" "),t=[],n=0;n<e.length;n++)t.push(e[n]+".repeater");return t.join(" ")},i.isElement=function(t){try{return t instanceof HTMLElement}catch(e){return"object"==typeof t&&1===t.nodeType&&"object"==typeof t.style&&"object"==typeof t.ownerDocument}},i.init()};