New issue

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

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

Already on GitHub? Sign in to your account

Add Customizer context #399

Open
wants to merge 86 commits into
base: master
from

Conversation

Projects
None yet
3 participants
@dlh01
Member

dlh01 commented Nov 15, 2015

This is a work-in-progress PR to add a Customizer context. If you want to take it for a spin, try the standalone plugin: https://github.com/dlh01/fieldmanager-beta-customize/.

What's included so far covers most of Fieldmanager's fields and their features, but questions about the implementation and known bugs are below.

Suggestions and feedback are appreciated!

Bugs

  • Fieldmanager_Datepicker doesn't work.
  • Fieldmanager_RichTextArea doesn't work (and I'm not sure what would go into fixing this).
  • Unnecessary _debounce() applies when updating an Autocomplete's hidden field.
  • There's no signal to the user if a field fails validation.
  • Any changes to field values from sanitizing aren't reflected in the form.
  • JS callbacks are not bound to dynamically added sections.
  • Fieldmanager_Colorpicker doesn't work.
  • Inline docs about the architecture are insufficient.
  • Missing unit tests.

Questions

  • Is there a better way to support postMessage settings? Currently, these settings work, but the preview receives a serialized string, and none of Fieldmanager's processing (e.g., validation) occurs beforehand. Replacing jQuery's serialize() with serializing into JSON (which would then be passed to both JS and PHP) could help here.
  • Is there a better way to reinitialize FM sortable fields or label macros than adding event handlers to fieldmanager.js?
  • Is it a problem to manually set the Autocomplete's hidden field value to "", which doesn't happen in other contexts?

Resolves #331.

dlh01 added some commits Oct 17, 2015

Enable autocomplete when focusing an autocomplete-ready field
Autocomplete fields in the Customizer are not likely to be visible when
`fm.autocomplete.enable_autocomplete()` first fires. Rather than adding
another FM-specific event, this triggers `enable_autocomplete()`
whenever an uninitialized autocomplete input is focused.

Bonus: This affects autocomplete fields in widgets and menu items, too.
Allow init_sortable() and init_label_macros() to be triggered externally
These handlers allow contexts (immediately, the Customizer context) or
third-party extensions to reinitialize these features after events not
relevant to fieldmanager.js.
@danielbachhuber

This comment has been minimized.

Show comment
Hide comment
@danielbachhuber

danielbachhuber Nov 16, 2015

Collaborator

💯

Collaborator

danielbachhuber commented Nov 16, 2015

💯

dlh01 added some commits Nov 22, 2015

Include jQuery Datepicker as Datepicker dependency
This helps ensure the UI Datepicker script loads when adding a
Datepicker field to the Customizer.
Replace per-field JS handlers with Customizer event
This removes the two event handlers that existed only to enable sortable
fields and label macros. Instead, we trigger one event when a Customizer
section containing a Fieldmanager control expands, and have those
features listen for it. This is a little more consistent with other FM
features that listen for FM-related events.
Initialize display-if triggers in the Customizer
Moves the initialization logic to a function so it can be called during
'fm_customizer_control_section_expanded'.
@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Dec 2, 2015

Member

The last round of changes to this PR should have fixed Datepicker fields and the _debounce() delay on Autocomplete fields. It also fixed display_if, which wasn't working at all.

Is there a better way to reinitialize FM sortable fields or label macros than adding event handlers to fieldmanager.js?

I've answered this question for now as "yes" and added a fm_customizer_control_section_expanded trigger, which other scripts in FM can bind to. This seems a little more consistent to me with other FM JS behavior.

Member

dlh01 commented Dec 2, 2015

The last round of changes to this PR should have fixed Datepicker fields and the _debounce() delay on Autocomplete fields. It also fixed display_if, which wasn't working at all.

Is there a better way to reinitialize FM sortable fields or label macros than adding event handlers to fieldmanager.js?

I've answered this question for now as "yes" and added a fm_customizer_control_section_expanded trigger, which other scripts in FM can bind to. This seems a little more consistent to me with other FM JS behavior.

@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Dec 3, 2015

Member

Any changes to field values from sanitizing aren't reflected in the form.

This seems to be an issue with core controls as well, so I've marked it as "done," for now, in that Fieldmanager doesn't introduce it.

Member

dlh01 commented Dec 3, 2015

Any changes to field values from sanitizing aren't reflected in the form.

This seems to be an issue with core controls as well, so I've marked it as "done," for now, in that Fieldmanager doesn't introduce it.

@@ -77,5 +77,9 @@ fm.autocomplete = {
$( document ).ready( fm.autocomplete.enable_autocomplete );
$( document ).on( 'fm_collapsible_toggle fm_added_element fm_displayif_toggle fm_activate_tab', fm.autocomplete.enable_autocomplete );
$( document ).on( 'focus',
'input[class*="fm-autocomplete"]:not(.fm-autocomplete-enabled)',

This comment has been minimized.

@danielbachhuber

danielbachhuber Dec 3, 2015

Collaborator

Do we need the prior to implementation approaches in addition to this approach?

@danielbachhuber

danielbachhuber Dec 3, 2015

Collaborator

Do we need the prior to implementation approaches in addition to this approach?

This comment has been minimized.

@dlh01

dlh01 Dec 3, 2015

Member

I don't think so. But the existing JS predates my involvement with FM, so I'd appreciate a review from you or someone else to confirm.

@dlh01

dlh01 Dec 3, 2015

Member

I don't think so. But the existing JS predates my involvement with FM, so I'd appreciate a review from you or someone else to confirm.

dlh01 added some commits Dec 6, 2015

Alert users to failed validation during saving
This primarily updates Fieldmanager_Field::_failed_validation() so that
it returns usable data to the Customizer. The particular error string
and the method of alerting users might come in for more updates.
@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Dec 6, 2015

Member

0795c83 updates the behavior in Fieldmanager_Field::_failed_validation() to account for the Customizer, and it provides an alert() to the user if validation fails while attempting to save changes.

At the moment, there doesn't seem to be a standard way to alert users to errors while saving changes in the Customizer. alert() is at least consistent with the "Are you sure" prompt, but it still isn't great, and suggestions for alternate approaches are welcome.

There also doesn't seem to be a great a way to send a message when an error occurs while previewing a setting change. Failing validation will still stop the preview from using invalid values, but it does so silently. Suggestions welcome here, too.

Member

dlh01 commented Dec 6, 2015

0795c83 updates the behavior in Fieldmanager_Field::_failed_validation() to account for the Customizer, and it provides an alert() to the user if validation fails while attempting to save changes.

At the moment, there doesn't seem to be a standard way to alert users to errors while saving changes in the Customizer. alert() is at least consistent with the "Are you sure" prompt, but it still isn't great, and suggestions for alternate approaches are welcome.

There also doesn't seem to be a great a way to send a message when an error occurs while previewing a setting change. Failing validation will still stop the preview from using invalid values, but it does so silently. Suggestions welcome here, too.

dlh01 added some commits Dec 7, 2015

Bind FM event to Sections as they're added
This helps ensure we bind 'fm_customizer_control_section_expanded' to
sections that are dynamically added.

This also changes the previous behavior of binding to only sections with
Fieldmanager controls: If an FM control is dynamically added to a
section that had no FM controls, we need to trigger the event when that
section expands.

Binding to when controls are added, rather than sections, isn't enough
because controls can be added without being assigned to sections.
Eventually, it might be more efficient to try binding to a section only
when a Fieldmanager control is added to it.
Offer suggestion after saving in Customizer fails
This follows other FM error messages, e.g. "You may be able to use your
browser's back button" and "Please check your code and try again."
Don't reserialize all controls on changes in value
Instead, reserialize only those controls containing the changed element.
Fix some saving callbacks after d6330b4
- After dropping a sortable field, pass the available element directly
  to reserializeControlsContainingElement()
- Call reserializeEachControl() after removing fields or values, because
  they no longer exist and so the control doesn't contain them.
Serialize FM Control values into JS objects
When previewing or saving a Fieldmanager field in the Customizer, we now
use the jquery.serializeJSON][1] library to serialize the FM control
into a JavaScript object. The object is then set as value of the
control's setting.

This allows us to send an object both to PHP, as part of a 'refresh'
setting, and to JS, as part of a 'postMessage' setting. Previously each
received a string from jQuery's `serialize()`, which remains the
fallback behavior.

[1]: https://github.com/marioizquierdo/jquery.serializeJSON
@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Jan 26, 2016

Member

Is there a better way to support postMessage settings?

01893e7 adds the serializeJSON library for converting the value of an FM field inside a control into an object, which can then be handled more easily in PHP or JS.

Member

dlh01 commented Jan 26, 2016

Is there a better way to support postMessage settings?

01893e7 adds the serializeJSON library for converting the value of an FM field inside a control into an object, which can then be handled more easily in PHP or JS.

dlh01 added some commits Jan 30, 2016

stripslashes_deep(), use context API when saving
stripslashes_deep() matches existing submenu saving behavior.
Pass context, not field, to Customize control
This lets the context manage the field object, rather than passing the
field to both the context and the control. It also lets us use the
context's own API for rendering instead of echoing it ourselves.
@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Jan 30, 2016

Member

8066242 and the few commits preceding it should get Fieldmanager_RichTextAreas working in the Customizer context.

Member

dlh01 commented Jan 30, 2016

8066242 and the few commits preceding it should get Fieldmanager_RichTextAreas working in the Customizer context.

dlh01 added some commits Jan 30, 2016

Don't reserialize each control on 'ready'
This takes a slightly more limited approach to reserializing controls so
that their default values take effect.
Introduce Fieldmanager_Customize_Setting
The new object sets the default value, sanitize callback, and type where
those were previously passed as constructor arguments.

we also extend the _preview_filter() so we can call value() during the
default sanitizing callback, fetching the current option value for
Fieldmanager_Field::presave_all(), without creating an infinite loop.
Being able to call value() means we can remove the
Fieldmanager_Context_Customizer::current_value logic, which didn't
account for newly saved values from the Customizer anyway.

Also includes a bit of restructuring to make the context and the objects
it creates easier to extend.

Adds PHP tests for new classes.

@dlh01 dlh01 reopened this Mar 18, 2016

@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Mar 18, 2016

Member

Reopening, now with 2396297, which attempts to increase the context's flexibility by loosening its connection to Customizer sections.

Member

dlh01 commented Mar 18, 2016

Reopening, now with 2396297, which attempts to increase the context's flexibility by loosening its connection to Customizer sections.

dlh01 added some commits May 15, 2016

Render Fieldmanager_Customize_Control::label and ::description
Although Fieldmanager has its own version of these properties, there
isn't a technical reason to ignore the `WP_Customize_Control` versions,
and developers might still want to use them if other Customizer
functionality hooks into the markup.
Support core's Customizer setting validation
When core's setting validation is not available, invalid values will
still be rejected, but there won't be a notice.

Reverts 0795c83 and
bd39fe8, which added kludgy support for
alerting users to validation errors.
Revert "Support core's Customizer setting validation"
Because core's Customizer validation infrastructure might change until
the next stable release, hold off on using it. See, e.g.,
https://core.trac.wordpress.org/ticket/37247.

This reverts commit 85f1efb.
Use context's validation callback with FM settings
Adds a check for the `'customize_validation_'` filter in
`Fieldmanager_Customize_Setting::_preview_filter()` to avoid an infinite
loop, much like the check for the `'customize_sanitize_'` filter.
Parse query-string values before validating
Moves the logic for converting the `jQuery.serialize()`'d string of a
field value into the array or string to save.
Reject invalid values from sanitize callback
When the context can use the Customizer's validation framework, and when
the default callbacks are added to FM Customizer settings, any invalid
submissions will have already been rejected before sanitizing occurs.

But, we still need to check for invalid values in the sanitizing
callback just in case, for example, the method is called on its own or
the validation callback is not hooked to the Customizer setting. If a
field value is invalid, we need to reject the update with a
Customizer-approved `WP_Error` or `null` before Fieldmanager's native
validation routines (such as throwing an Exception or calling
`wp_die()`) kick in.
Test catching invalid values while sanitizing
Adds a data provider, `data_field_debug()`, for testing the same method
while `Fieldmanager_Field::debug` is `true` or `false`, because the
`$debug` property affects Fieldmanager's response to invalid
values. These tests currently fail when `$debug` is false.
Handle calls to `wp_die()` on validation error
Adds a handler to the Customizer context that intercepts `wp_die()` and
throws it as an exception which the default validation callback can catch.
Update `Fieldmanager_RichTextArea::customize_controls_print_footer_sc…
…ripts()` priority

This method was previously hooked to an earlier priority than when it
was actually called, which is invalid under `WP_Hook`. See
https://core.trac.wordpress.org/ticket/38011.
Standardize on 'Customize' for objects
'Customizer' for the thing itself.

dlh01 added a commit to dlh01/fieldmanager-beta-customize that referenced this pull request Oct 12, 2016

Initial merge as a beta plugin
Includes all of the changes from the Pull Request into Fieldmanager (see
alleyinteractive/wordpress-fieldmanager#399)
except for the unit tests, which will take some more work to decouple.

@dlh01 dlh01 referenced this pull request Oct 12, 2016

Merged

Initial merge as a beta plugin #1

@dlh01

This comment has been minimized.

Show comment
Hide comment
@dlh01

dlh01 Oct 17, 2016

Member

The proposed Customize context is now available as a standalone plugin that you can use alongside a stable version of Fieldmanager: Check out Fieldmanager Beta: Customize (props @jameswburke for reviewing the initial pull request).

Screenshots, installation instructions, details about how the plugin integrates with Fieldmanager, and steps to activate a demo are all available in the README.

If you're interested in using the Customize context, please try the plugin. Feedback, bug reports, and pull requests are all welcome at the repo.

Plugin development will continue much like a feature plugin in WordPress core. Improvements to the plugin based on testing will, hopefully, strengthen this pull request in turn.

Member

dlh01 commented Oct 17, 2016

The proposed Customize context is now available as a standalone plugin that you can use alongside a stable version of Fieldmanager: Check out Fieldmanager Beta: Customize (props @jameswburke for reviewing the initial pull request).

Screenshots, installation instructions, details about how the plugin integrates with Fieldmanager, and steps to activate a demo are all available in the README.

If you're interested in using the Customize context, please try the plugin. Feedback, bug reports, and pull requests are all welcome at the repo.

Plugin development will continue much like a feature plugin in WordPress core. Improvements to the plugin based on testing will, hopefully, strengthen this pull request in turn.

@mboynes mboynes modified the milestones: 1.2.0, later Oct 8, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment