Commit 056f1053 authored by Kevin Stover's avatar Kevin Stover

Merging develop into master.

parents fa82c203 d3ec1dbe
......@@ -3,8 +3,8 @@
Tags: form, forms, contact form, custom form, form builder, form creator, form manager, form creation, contact forms, custom forms, forms builder, forms creator, forms manager, forms creation, form administration,
Requires at least: 4.4
Tested up to: 4.6
Stable tag: 3.0.16
Tested up to: 4.6.1
Stable tag: 3.0.17
License: GPLv2 or later
With a simple drag and drop interface you can create contact forms, email subscription forms, order forms, payment forms, and any other type of form for your WordPress site.
......
......@@ -948,10 +948,12 @@ All styles used within the drawer
text-indent: -99999px; }
.nf-action-items.available .nf-item.nf-has-img {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
opacity: 0.6; }
.nf-action-items.available .nf-item.nf-has-img:hover {
filter: grayscale(0);
-webkit-filter: grayscale(0);
filter: grayscale(0);
opacity: 1.0; }
.nf-field-type-button {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -299,6 +299,7 @@ body .pika-label {
height: auto; }
.nf-form-wrap .note-editor .dropdown-toggle {
position: relative;
display: inline-block;
top: 0; }
.nf-form-wrap .note-editor .dropdown-toggle::after {
content: "";
......@@ -814,6 +815,7 @@ ADJUST SOME LABEL LEFT & RIGHT ISSUES
.label-right .listradio-wrap .nf-field-label,
.label-right .listcheckbox-wrap .nf-field-label {
-ms-flex-align: start;
-ms-grid-row-align: flex-start;
align-items: flex-start; }
.label-left .textarea-wrap .nf-field-label,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -299,6 +299,7 @@ body .pika-label {
height: auto; }
.nf-form-wrap .note-editor .dropdown-toggle {
position: relative;
display: inline-block;
top: 0; }
.nf-form-wrap .note-editor .dropdown-toggle::after {
content: "";
......@@ -814,6 +815,7 @@ ADJUST SOME LABEL LEFT & RIGHT ISSUES
.label-right .listradio-wrap .nf-field-label,
.label-right .listcheckbox-wrap .nf-field-label {
-ms-flex-align: start;
-ms-grid-row-align: flex-start;
align-items: flex-start; }
.label-left .textarea-wrap .nf-field-label,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -299,6 +299,7 @@ body .pika-label {
height: auto; }
.nf-form-wrap .note-editor .dropdown-toggle {
position: relative;
display: inline-block;
top: 0; }
.nf-form-wrap .note-editor .dropdown-toggle::after {
content: "";
......@@ -814,6 +815,7 @@ ADJUST SOME LABEL LEFT & RIGHT ISSUES
.label-right .listradio-wrap .nf-field-label,
.label-right .listcheckbox-wrap .nf-field-label {
-ms-flex-align: start;
-ms-grid-row-align: flex-start;
align-items: flex-start; }
.label-left .textarea-wrap .nf-field-label,
......
This diff is collapsed.
......@@ -92,8 +92,11 @@ define( [], function() {
if( 'undefined' != typeof fieldTypes && 0 != fieldTypes.length ) {
_.each( fieldTypes, function( fieldType ){
var fieldTypeModel = nfRadio.channel( 'fields' ).request( 'get:type', fieldType );
options.push({
label: '-- Add ' + fieldType + ' Field',
label: '-- Add ' + fieldTypeModel.get( 'nicename' ) + ' Field',
value: 'addField:' + fieldType,
});
} );
......
......@@ -77,9 +77,28 @@ define( ['views/app/drawer/mergeTagsContent', 'views/app/drawer/settingError'],
*/
nfRadio.channel( 'setting-' + this.model.get( 'name' ) ).trigger( 'destroy:setting', this.model, this.dataModel, this );
nfRadio.channel( 'setting-type-' + this.model.get( 'type' ) ).trigger( 'destroy:setting', this.model, this.dataModel, this );
/*
* Unescape any HTML being saved if we are a textbox.
*/
if ( 'textbox' == this.model.get( 'type' ) ) {
var setting = this.model.get( 'name' );
var value = this.dataModel.get( setting );
this.dataModel.set( setting, _.unescape( value ), { silent: true } );
}
},
onBeforeRender: function() {
/*
* We want to escape any HTML being output if we are a textbox.
*/
if ( 'textbox' == this.model.get( 'type' ) ) {
var setting = this.model.get( 'name' );
var value = this.dataModel.get( setting );
this.dataModel.set( setting, _.escape( value ), { silent: true } );
}
nfRadio.channel( 'app' ).trigger( 'before:renderSetting', this.model, this.dataModel );
nfRadio.channel( 'setting-type-' + this.model.get( 'type' ) ).trigger( 'before:renderSetting', this.model, this.dataModel, this );
nfRadio.channel( 'setting-' + this.model.get( 'name' ) ).trigger( 'before:renderSetting', this.model, this.dataModel, this );
......
......@@ -26,17 +26,35 @@ define( ['views/app/drawer/optionRepeaterError'], function( ErrorView ) {
this.hasErrors = false;
},
onBeforeDestroy: function() {
onBeforeDestroy: function() {
this.model.off( 'change', this.render );
this.model.off( 'change:errors', this.renderErrors );
},
onBeforeRender: function() {
/*
* We want to escape any HTML being output for our label.
*/
if ( this.model.get( 'label' ) ) {
var label = this.model.get( 'label' );
this.model.set( 'label', _.escape( label ), { silent: true } );
}
},
onRender: function() {
nfRadio.channel( 'mergeTags' ).request( 'init', this );
/*
* Send out a radio message.
*/
nfRadio.channel( 'setting-' + this.settingModel.get( 'name' ) + '-option' ).trigger( 'render:setting', this.model, this.dataModel, this );
/*
* We want to unescape any HTML being output for our label.
*/
if ( this.model.get( 'label' ) ) {
var label = this.model.get( 'label' );
this.model.set( 'label', _.unescape( label ), { silent: true } );
}
},
onShow: function() {
......@@ -53,6 +71,7 @@ define( ['views/app/drawer/optionRepeaterError'], function( ErrorView ) {
},
changeOption: function( e ) {
nfRadio.channel( 'option-repeater' ).trigger( 'change:option', e, this.model, this.dataModel, this.settingModel );
},
......
......@@ -9,6 +9,10 @@ define([], function() {
if ( 'undefined' != typeof response.data.actions.success_message && '' != response.data.actions.success_message ) {
var form_id = response.data.form_id;
jQuery( '#nf-form-' + form_id + '-cont .nf-response-msg' ).html( response.data.actions.success_message );
jQuery('html, body').animate({
scrollTop: ( jQuery( '#nf-form-' + form_id + '-cont .nf-response-msg' ).offset().top - 50 )
}, 0 );
}
}
}
......
......@@ -24,7 +24,7 @@ define( [ 'views/fieldCollection', 'models/fieldCollection' ], function( FieldCo
},
defaultFormContentLoad: function( formContentData, formModel, context ) {
var fieldCollection = nfRadio.channel( 'fields' ).request( 'get:collection' );
var fieldCollection = formModel.get( 'fields' );
/*
* If we only have one load filter, we can just return the field collection.
*/
......@@ -36,12 +36,27 @@ define( [ 'views/fieldCollection', 'models/fieldCollection' ], function( FieldCo
return formModel.get( 'fields' ).findWhere( { key: key } );
}, this );
return new FieldCollection( fieldModels );
var currentFieldCollection = new FieldCollection( fieldModels );
fieldCollection.on( 'reset', function( collection ) {
var resetFields = [];
currentFieldCollection.each( function( fieldModel ) {
if ( 'submit' != fieldModel.get( 'type' ) ) {
resetFields.push( collection.findWhere( { key: fieldModel.get( 'key' ) } ) );
} else {
resetFields.push( fieldModel );
}
} );
currentFieldCollection.reset( resetFields );
} );
return currentFieldCollection;
},
defaultFormContentView: function() {
return FieldCollectionView;
},
}
});
......
......@@ -5,6 +5,8 @@ define([], function() {
var controller = Marionette.Object.extend( {
initialize: function() {
this.listenTo( nfRadio.channel( 'form' ), 'render:view', this.initHelpText );
nfRadio.channel( 'form' ).reply( 'init:help', this.initHelpText );
},
initHelpText: function( view ) {
......
......@@ -31,6 +31,9 @@ define(['controllers/submitButton'], function( submitButton ) {
},
maybeDisable: function( fieldModel ) {
if( fieldModel.get( 'formID' ) != this.get( 'formID' ) ) return;
this.set( 'disabled', true );
this.trigger( 'reRender' );
},
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -62,6 +62,7 @@
}
.dropdown-toggle {
position: relative;
display: inline-block;
top: 0;
&::after {
content: "";
......
......@@ -265,7 +265,7 @@ class Ninja_Forms {
// Plugin version
if ( ! defined( 'NF_PLUGIN_VERSION' ) )
define( 'NF_PLUGIN_VERSION', '3.0.16' );
define( 'NF_PLUGIN_VERSION', '3.0.17' );
// Plugin Folder Path
if ( ! defined( 'NF_PLUGIN_DIR' ) )
......
......@@ -80,6 +80,7 @@ gulp.task('js:frontend', function(){
gulp.src([
'assets/js/lib/bootstrap.min.js',
'assets/js/lib/modernizr.min.js',
'assets/js/lib/codemirror.min.js',
'assets/js/lib/codemirror-xml.min.js',
'assets/js/lib/codemirror-formatting.min.js',
......@@ -104,7 +105,6 @@ gulp.task('js:frontend', function(){
'assets/js/lib/backbone.marionette.min.js',
'assets/js/lib/backbone.radio.min.js',
'assets/js/lib/math.min.js',
'assets/js/lib/modernizr.min.js',
'assets/js/min/global.js',
])
.pipe(concat('front-end-deps.js'))
......
......@@ -331,8 +331,10 @@ class NF_Abstracts_Model
*/
public function update_settings( $data )
{
foreach( $data as $key => $value ){
$this->update_setting( $key, $value );
if( is_array( $data ) ) {
foreach ($data as $key => $value) {
$this->update_setting($key, $value);
}
}
return $this;
......
......@@ -175,7 +175,7 @@ class NF_Admin_CPT_Submission
if( is_numeric( $column ) ){
$value = $sub->get_field_value( $column );
$field = Ninja_Forms()->form()->get_field( $column );
echo apply_filters( 'ninja_forms_custom_columns', $value, $field );
echo apply_filters( 'ninja_forms_custom_columns', $value, $field, $sub_id );
}
}
......@@ -252,11 +252,21 @@ class NF_Admin_CPT_Submission
$fields = Ninja_Forms()->form( $form_id )->get_fields();
usort( $fields, array( $this, 'sort_fields' ) );
$hidden_field_types = apply_filters( 'nf_sub_hidden_field_types', array() );
Ninja_Forms::template( 'admin-metabox-sub-fields.html.php', compact( 'fields', 'sub', 'hidden_field_types' ) );
}
public static function sort_fields( $a, $b )
{
if ( $a->get_setting( 'order' ) == $b->get_setting( 'order' ) ) {
return 0;
}
return ( $a->get_setting( 'order' ) < $b->get_setting( 'order' ) ) ? -1 : 1;
}
/**
* Info Meta Box
*
......
......@@ -8,11 +8,11 @@ final class NF_Admin_Menus_ImportExport extends NF_Abstracts_Submenu
public function __construct()
{
add_action( 'plugins_loaded', array( $this, 'import_form_listener' ) );
add_action( 'plugins_loaded', array( $this, 'export_form_listener' ) );
add_action( 'init', array( $this, 'import_form_listener' ), 0 );
add_action( 'init', array( $this, 'export_form_listener' ), 0 );
add_action( 'plugins_loaded', array( $this, 'import_fields_listener' ) );
add_action( 'plugins_loaded', array( $this, 'export_fields_listener' ) );
add_action( 'init', array( $this, 'import_fields_listener' ), 0 );
add_action( 'init', array( $this, 'export_fields_listener' ), 0 );
add_filter( 'ninja_forms_before_import_fields', array( $this, 'import_fields_backwards_compatibility' ) );
......
......@@ -8,7 +8,7 @@ final class NF_Admin_Metaboxes_AppendAForm extends NF_Abstracts_Metabox
{
parent::__construct();
$this->_title = __( 'Append a Ninja Forms', 'ninja-forms' );
$this->_title = __( 'Append a Ninja Form', 'ninja-forms' );
add_filter( 'the_content', array( $this, 'append_form' ) );
}
......
......@@ -387,6 +387,10 @@ return apply_filters( 'ninja_forms_field_settings', array(
'label' => __( 'DD-MM-YYYY', 'ninja-forms' ),
'value' => 'DD-MM-YYYY',
),
array(
'label' => __( 'DD.MM.YYYY', 'ninja-forms' ),
'value' => 'DD.MM.YYYY',
),
array(
'label' => __( 'MM/DD/YYYY', 'ninja-forms' ),
'value' => 'MM/DD/YYYY',
......@@ -395,6 +399,10 @@ return apply_filters( 'ninja_forms_field_settings', array(
'label' => __( 'MM-DD-YYYY', 'ninja-forms' ),
'value' => 'MM-DD-YYYY',
),
array(
'label' => __( 'MM.DD.YYYY', 'ninja-forms' ),
'value' => 'MM.DD.YYYY',
),
array(
'label' => __( 'YYYY-MM-DD', 'ninja-forms' ),
'value' => 'YYYY-MM-DD',
......@@ -403,6 +411,10 @@ return apply_filters( 'ninja_forms_field_settings', array(
'label' => __( 'YYYY/MM/DD', 'ninja-forms' ),
'value' => 'YYYY/MM/DD',
),
array(
'label' => __( 'YYYY.MM.DD', 'ninja-forms' ),
'value' => 'YYYY.MM.DD',
),
array(
'label' => __( 'Friday, November 18, 2019', 'ninja-forms' ),
'value' => 'dddd, MMMM D YYYY',
......
......@@ -41,4 +41,30 @@ return apply_filters( 'ninja_forms_merge_tags_post', array(
'callback' => 'post_url'
),
/*
|--------------------------------------------------------------------------
| Post Author
|--------------------------------------------------------------------------
*/
'author' => array(
'id' => 'author',
'tag' => '{post:author}',
'label' => __( 'Post Author', 'ninja_forms' ),
'callback' => 'post_author'
),
/*
|--------------------------------------------------------------------------
| Post Author Email
|--------------------------------------------------------------------------
*/
'author_email' => array(
'id' => 'author_email',
'tag' => '{post:author_email}',
'label' => __( 'Post Author Email', 'ninja_forms' ),
'callback' => 'post_author_email'
),
));
\ No newline at end of file
......@@ -41,4 +41,30 @@ return apply_filters( 'ninja_forms_merge_tags_system', array(
'callback' => 'system_ip'
),
/*
|--------------------------------------------------------------------------
| Site Title
|--------------------------------------------------------------------------
*/
'site_title' => array(
'id' => 'site_title',
'tag' => '{site:title}',
'label' => __( 'Site Title', 'ninja_forms' ),
'callback' => 'site_title'
),
/*
|--------------------------------------------------------------------------
| Site URL
|--------------------------------------------------------------------------
*/
'site_url' => array(
'id' => 'site_url',
'tag' => '{site:url}',
'label' => __( 'Site URL', 'ninja_forms' ),
'callback' => 'site_url'
),
));
\ No newline at end of file
......@@ -298,6 +298,8 @@ final class NF_Database_Models_Submission
$fields = Ninja_Forms()->form( $form_id )->get_fields();
usort( $fields, array( self, sort_fields ) );
$hidden_field_types = apply_filters( 'nf_sub_hidden_field_types', array() );
foreach( $fields as $field ){
......@@ -473,5 +475,13 @@ final class NF_Database_Models_Submission
return $field_id;
}
public static function sort_fields( $a, $b )
{
if ( $a->get_setting( 'order' ) == $b->get_setting( 'order' ) ) {
return 0;
}
return ( $a->get_setting( 'order' ) < $b->get_setting( 'order' ) ) ? -1 : 1;
}
} // End NF_Database_Models_Submission
......@@ -234,8 +234,9 @@ final class NF_Display_Render
$settings[ 'options' ] = apply_filters( 'ninja_forms_render_options_' . $field_type, $settings[ 'options' ], $settings );
}
if (isset($settings['default'])) {
$default_value = apply_filters('ninja_forms_render_default_value', $settings['default'], $field_type, $settings);
$default_value = ( isset( $settings[ 'default' ] ) ) ? $settings[ 'default' ] : null;
$default_value = apply_filters('ninja_forms_render_default_value', $default_value, $field_type, $settings);
if ( $default_value ) {
$default_value = preg_replace( '/{.*}/', '', $default_value );
......@@ -428,8 +429,9 @@ final class NF_Display_Render
$field['settings'][ 'options' ] = apply_filters( 'ninja_forms_render_options_' . $field['settings'][ 'type' ], $field['settings'][ 'options' ], $field['settings'] );
}
if (isset($field['settings']['default'])) {
$default_value = apply_filters('ninja_forms_render_default_value', $field['settings']['default'], $field_type, $field['settings']);
$default_value = ( isset( $field[ 'settings' ][ 'default' ] ) ) ? $field[ 'settings' ][ 'default' ] : null;
$default_value = apply_filters( 'ninja_forms_render_default_value', $default_value, $field_type, $field[ 'settings' ]);
if( $default_value ){
$default_value = preg_replace( '/{.*}/', '', $default_value );
......
......@@ -40,11 +40,18 @@ class NF_Fields_Date extends NF_Fields_Textbox
$lookup = array(
'MM/DD/YYYY' => __( 'm/d/Y', 'ninja-forms' ),
'MM-DD-YYYY' => __( 'm-d-Y', 'ninja-forms' ),
'MM.DD.YYYY' => __( 'm.d.Y', 'ninja-forms' ),
'DD/MM/YYYY' => __( 'm/d/Y', 'ninja-forms' ),
'DD-MM-YYYY' => __( 'd-m-Y', 'ninja-forms' ),
'DD.MM.YYYY' => __( 'd.m.Y', 'ninja-forms' ),
'YYYY-MM-DD' => __( 'Y-m-d', 'ninja-forms' ),
'YYYY/MM/DD' => __( 'Y/m/d', 'ninja-forms' ),
'dddd, MMMM D YYYY' => __( 'l, F d Y', 'ninja-forms' )
'YYYY.MM.DD' => __( 'Y.m.d', 'ninja-forms' ),
'dddd, MMMM D YYYY' => __( 'l, F d Y', 'ninja-forms' ),
);
return ( isset( $lookup[ $format ] ) ) ? $lookup[ $format ] : $format;
......
......@@ -33,7 +33,7 @@ class NF_Fields_ListSelect extends NF_Abstracts_List
if( isset( $field[ 'options' ] ) ) {
foreach ($field['options'] as $option ) {
if( ! isset( $option[ 'value' ] ) || $value != $option[ 'value' ] || ! isset( $option[ 'calc' ] ) ) continue;
$value = $option[ 'calc' ];
return $option[ 'calc' ];
}
}
return $value;
......
......@@ -17,6 +17,8 @@ class NF_Fields_Recaptcha extends NF_Abstracts_Field
protected $_test_value = '';
protected $_settings = array( 'label' );
public function __construct()
{
parent::__construct();
......@@ -27,7 +29,7 @@ class NF_Fields_Recaptcha extends NF_Abstracts_Field
'name' => 'wrapper_class',
'type' => 'textbox',
'placeholder' => '',
'label' => __( 'Wrapper', 'ninja-forms' ),
'label' => __( 'Wrapper Class', 'ninja-forms' ),
'width' => 'full',
'value' => '',
'group' => 'primary',
......@@ -36,8 +38,6 @@ class NF_Fields_Recaptcha extends NF_Abstracts_Field
);
add_filter( 'nf_sub_hidden_field_types', array( $this, 'hide_field_type' ) );
// add_filter( 'script_loader_tag', array( $this, 'add_script_attributes' ), 10, 2);
}
public function localize_settings( $settings, $form ) {
......@@ -75,10 +75,4 @@ class NF_Fields_Recaptcha extends NF_Abstracts_Field
$field_types[] = $this->_name;
return $field_types;
}
function add_script_attributes( $tag, $handle )
{
if ( 'google-recaptcha' !== $handle ) return $tag;
return str_replace( ' src', ' async="async" defer="defer" src', $tag );
}
}
......@@ -32,4 +32,20 @@ final class NF_MergeTags_Post extends NF_Abstracts_MergeTags
return ( is_object ( $post ) ) ? get_permalink( $post->ID ) : '';
}
protected function post_author()
{
global $post;
if( ! is_object( $post ) ) return;
$author = get_user_by('id', $post->post_author);
return $author->display_name;
}
protected function post_author_email()
{
global $post;
if( ! is_object( $post ) ) return;
$author = get_user_by( 'id', $post->post_author );
return $author->user_email;
}
} // END CLASS NF_MergeTags_System
......@@ -16,7 +16,10 @@ final class NF_MergeTags_System extends NF_Abstracts_MergeTags
protected function system_date()
{
$format = 'm/d/Y';
$format = Ninja_Forms()->get_setting( 'date_format' );
if ( empty( $format ) ) {
$format = 'Y/m/d';
}
return date( $format, time() );
}
......@@ -41,4 +44,14 @@ final class NF_MergeTags_System extends NF_Abstracts_MergeTags
return get_option( 'admin_email' );
}
protected function site_title()
{
return get_bloginfo( 'name' );
}
protected function site_url()
{
return get_bloginfo( 'url' );
}
} // END CLASS NF_MergeTags_System
......@@ -106,10 +106,10 @@ final class NF_Tracking
/**
* Check if a site is opted in
*
* @access private
* @access public
* @return bool
*/
private function is_opted_in()
public function is_opted_in()
{
return (bool) get_option( 'ninja_forms_allow_tracking', $this->is_freemius_opted_in() );
}
......@@ -150,10 +150,10 @@ final class NF_Tracking
/**
* Check if a site is opted out
*
* @access private
* @access public
* @return bool
*/
private function is_opted_out()
public function is_opted_out()
{
return (bool) get_option( 'ninja_forms_do_not_allow_tracking', $this->is_freemius_opted_out() );
}
......@@ -192,5 +192,3 @@ final class NF_Tracking
}
} // END CLASS NF_Tracking
new NF_Tracking();
\ No newline at end of file
......@@ -3,7 +3,7 @@
Plugin Name: Ninja Forms
Plugin URI: http://ninjaforms.com/
Description: Ninja Forms is a webform builder with unparalleled ease of use and features.
Version: 3.0.16
Version: 3.0.17
Author: The WP Ninjas
Author URI: http://ninjaforms.com
Text Domain: ninja-forms
......@@ -51,7 +51,7 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
/**
* @since 3.0
*/
const VERSION = '3.0.16';
const VERSION = '3.0.17';
/**
* @var Ninja_Forms
......@@ -134,6 +134,11 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
*/
protected $session = '';
/**
* @var NF_Tracking
*/
public $tracking;
/**
* Plugin Settings
*
......@@ -281,6 +286,11 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
self::$instance->widgets[] = new NF_Widget();
/*
* Opt-In Tracking
*/
self::$instance->tracking = new NF_Tracking();
/*
* Activation Hook
* TODO: Move to a permanent home.
......@@ -692,3 +702,63 @@ if( get_option( 'ninja_forms_load_deprecated', FALSE ) && ! ( isset( $_POST[ 'nf
}
}
}
// Scheduled Action Hook
function nf_optin_send_admin_email( ) {
/*
* If we aren't opted in, or we've specifically opted out, then return false.
*/
if ( ! Ninja_Forms()->tracking->is_opted_in() || Ninja_Forms()->tracking->is_opted_out() ) {
return false;
}
/*
* If we haven't already submitted our email to api.ninjaforms.com, submit it and set an option saying we have.
*/