diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..604c14c --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@keraweb.nl. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..9d8181e --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# Contribute to Off-Canvas Sidebars + +Community made patches, localizations, bug reports, and contributions are always welcome and are crucial to ensure that this plugin remains alive and strong. + +When contributing please ensure you follow the guidelines below so that we can keep on top of things. + +## Getting Started + +* Submit a ticket for your issue, assuming one does not already exist. + * https://github.com/JoryHogeveen/off-canvas-sidebars/issues + * Clearly describe the issue including steps to reproduce the bug. + * Make sure you fill in the earliest version that you know has the issue as well as the version of WordPress you're using. + +## Making Changes + +* Fork the repository on GitHub +* Make the changes to your forked repository's code + * Ensure you stick to the [WordPress Coding Standards](http://codex.wordpress.org/WordPress_Coding_Standards) + * This repository contains all files needed to properly configure your IDE with the correct coding standards and code style configuration. + * [PHP MD](https://github.com/JoryHogeveen/off-canvas-sidebars/blob/master/tests/phpmd.xml) + * [PHP CS](https://github.com/JoryHogeveen/off-canvas-sidebars/blob/master/tests/phpcs.xml) + * [ESLint](https://github.com/JoryHogeveen/off-canvas-sidebars/blob/master/tests/.eslintrc) + * [CSSLint](https://github.com/JoryHogeveen/off-canvas-sidebars/blob/master/tests/.csslintrc) +* Create a new branch, named with a issue prefix (if present) and some keywords on what is changed. + * Example: `#123-what-is-changed`. +* When committing, reference your issue (if present) and include a note about the fix. +* Push the changes to the branch you created and submit a pull request for the `dev` branch. + +At this point you're waiting on us to merge your pull request. We'll review all pull requests, and make suggestions and changes if necessary. + +# Additional Resources +* [General GitHub documentation](http://help.github.com/) +* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..673329b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ +## Expected Behavior + + +## Actual Behavior + + +## Steps to Reproduce the Problem + + 1. + 1. + 1. + +## Specifications + + - Plugin Version: + - WordPress Version: + - Other plugins installed: + - Theme: + - Browser: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4030f6f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +Fixes # + +## Proposed Changes + + - + - + - diff --git a/README.md b/.github/README.md similarity index 70% rename from README.md rename to .github/README.md index 6a1c065..43e1ce2 100644 --- a/README.md +++ b/.github/README.md @@ -6,6 +6,7 @@ Add off-canvas sidebars using the Slidebars jQuery plugin. [![WordPress Plugin downloads](https://img.shields.io/wordpress/plugin/dt/off-canvas-sidebars.svg?style=flat)](https://wordpress.org/plugins/off-canvas-sidebars/) [![WordPress Plugin rating](https://img.shields.io/wordpress/plugin/r/off-canvas-sidebars.svg?style=flat)](https://wordpress.org/plugins/off-canvas-sidebars/) [![Travis](https://secure.travis-ci.org/JoryHogeveen/off-canvas-sidebars.png?branch=master)](http://travis-ci.org/JoryHogeveen/off-canvas-sidebars) +[![Code Climate](https://codeclimate.com/github/JoryHogeveen/off-canvas-sidebars/badges/gpa.svg)](https://codeclimate.com/github/JoryHogeveen/off-canvas-sidebars) [![License](https://img.shields.io/badge/license-GPL--2.0%2B-green.svg)](https://github.com/JoryHogeveen/off-canvas-sidebars/blob/master/license.txt) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=YGPLMLU7XQ9E8&lc=NL&item_name=Off%2dCanvas%20Sidebars&item_number=JWPP%2dOCS¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) @@ -15,7 +16,7 @@ This plugin will add various options to implement off-canvas sidebars in your Wo ### Overview / Features * Add off-canvas sidebars to the left, right, top and bottom of your website * Use sidebar areas (widget-ready areas), menu locations or [custom hooks](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Actions-&-Filters) to place content into the off-canvas sidebars -* You can add control buttons with a widget, a menu item or with [custom code](https://wordpress.org/plugins/off-canvas-sidebars/installation/) +* You can add control buttons with a widget, menu item, [shortcode](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Shortcodes) or with [custom code](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) * Various customisation options and settings available in the Appearances menu ### Compatibility (IMPORTANT!) @@ -24,10 +25,16 @@ The structure of your theme is of great importance for this plugin. Please read This plugin should work with most themes and plugins although I can't be sure for all use-cases. At this point it's still a 0.x version... If the plugin does not work for your theme, please let me know through the support and add a plugins and themes list and I will take a look! +#### Fixed elements (like sticky menu's) +There are known issues with fixed elements and Slidebars. [Click here for more information](https://www.adchsm.com/slidebars/help/advanced-usage/elements-with-fixed-positions/) +I've created two possible solutions for this: + +1. Legacy CSS solution. Use basic CSS2 positioning instead of CSS3 transform with hardware acceleration. +2. JavaScript solution. It is slower but still allows the use of hardware acceleration. + ### It's not working! / I found a bug! -Please let me know through the support and add a plugins and themes list! :) -https://wordpress.org/support/plugin/off-canvas-sidebars -Or submit an issue here on GitHub +Please let me know through [support](https://wordpress.org/support/plugin/off-canvas-sidebars) and add a plugins and themes list! :) +Or [submit an issue here on GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/issues) ### Credits * Slidebars jQuery plugin by [Adam](https://www.adchsm.com/slidebars/ "Adam"), thank you for this great plugin! @@ -45,8 +52,12 @@ Or search for "Off-Canvas Sidebars" via your plugins menu. ### Theme setup -Off-Canvas Sidebars won't work "out of the box" with most themes, please read the Wiki! -[Click here!](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) +Off-Canvas Sidebars won't work "out of the box" with most themes, please read the documentation! +[Click here for theme setup documentation.](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) + +### Actions | Filters | API + +* [See Wiki on GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki) ### Other Notes You can find me here: diff --git a/css/off-canvas-sidebars-admin.css b/css/off-canvas-sidebars-admin.css index 59d3cf0..e3fd97b 100644 --- a/css/off-canvas-sidebars-admin.css +++ b/css/off-canvas-sidebars-admin.css @@ -1,9 +1,10 @@ -/** +/*! * Off-Canvas Sidebars plugin * * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3 + * @version 0.4 + * @preserve */ .ocs-credits { @@ -17,6 +18,8 @@ .ocs-credits .inner { padding-left: 10px; padding-right: 10px; } .ocs-credits h3 { font-size: 14px; line-height: 1.4; margin: 0; padding: 8px 12px; border-bottom: 1px solid #eee; } +.off-canvas-sidebars-settings .postbox-container { float: none; } + .postbox.section-sidebar { -webkit-transition: all .1s; -moz-transition: all .1s; @@ -25,6 +28,16 @@ } .postbox.section-sidebar:hover { opacity: 1 !important; } +.off-canvas-sidebars-settings .form-table tbody > tr:not(:last-child) { border-bottom: 1px solid #eee; } +.off-canvas-sidebars-settings .form-table:not(:last-child) { margin-bottom: 1em; border-bottom: 1px solid #eee; } + +.off-canvas-sidebars-settings fieldset.radio label, +.off-canvas-sidebars-settings fieldset.checkbox label { display: block } +.off-canvas-sidebars-settings fieldset.radio label + br { display: none; } +.off-canvas-sidebars-settings fieldset.radio label + .description { margin-bottom: .5em; display: inline-block; } + +.off-canvas-sidebars-settings input + select { vertical-align: top; } + @media only screen and (min-width: 850px) { .off-canvas-sidebars-settings { margin-right: 300px; @@ -41,6 +54,14 @@ margin: 10px -300px 10px 20px; width: 280px; } + + .off-canvas-sidebars-settings .postbox-container .postbox-third { + float: left; + width: 33%; + margin-left: 0.5%; + box-sizing: border-box; + } + .off-canvas-sidebars-settings .postbox-container .postbox-third.first { margin-left: 0; } } @media only screen and (min-width: 959px) { diff --git a/css/off-canvas-sidebars-admin.min.css b/css/off-canvas-sidebars-admin.min.css new file mode 100644 index 0000000..fbbc535 --- /dev/null +++ b/css/off-canvas-sidebars-admin.min.css @@ -0,0 +1,9 @@ +/*! + * Off-Canvas Sidebars plugin + * + * @author Jory Hogeveen + * @package off-canvas-sidebars + * @version 0.4 + * @preserve + */ +.ocs-credits{overflow:hidden;background:#fff;position:relative;margin:0;box-shadow:0 0 0 1px rgba(0,0,0,0.05)}.ocs-credits .inner{padding-left:10px;padding-right:10px}.ocs-credits h3{font-size:14px;line-height:1.4;margin:0;padding:8px 12px;border-bottom:1px solid #eee}.off-canvas-sidebars-settings .postbox-container{float:none}.postbox.section-sidebar{-webkit-transition:all .1s;-moz-transition:all .1s;-o-transition:all .1s;transition:all .1s}.postbox.section-sidebar:hover{opacity:1 !important}.off-canvas-sidebars-settings .form-table tbody>tr:not(:last-child){border-bottom:1px solid #eee}.off-canvas-sidebars-settings .form-table:not(:last-child){margin-bottom:1em;border-bottom:1px solid #eee}.off-canvas-sidebars-settings fieldset.radio label,.off-canvas-sidebars-settings fieldset.checkbox label{display:block}.off-canvas-sidebars-settings fieldset.radio label+br{display:none}.off-canvas-sidebars-settings fieldset.radio label+.description{margin-bottom:.5em;display:inline-block}.off-canvas-sidebars-settings input+select{vertical-align:top}@media only screen and (min-width:850px){.off-canvas-sidebars-settings{margin-right:300px}.off-canvas-sidebars-settings form{float:left;min-width:100%;width:auto}.ocs-credits{float:right;margin:10px -300px 10px 20px;width:280px}.off-canvas-sidebars-settings .postbox-container .postbox-third{float:left;width:33%;margin-left:.5%;box-sizing:border-box}.off-canvas-sidebars-settings .postbox-container .postbox-third.first{margin-left:0}}@media only screen and (min-width:959px){.ocs-credits{position:fixed;right:0;margin:10px 20px}} \ No newline at end of file diff --git a/css/off-canvas-sidebars.css b/css/off-canvas-sidebars.css index 77ec34d..2d6d135 100644 --- a/css/off-canvas-sidebars.css +++ b/css/off-canvas-sidebars.css @@ -1,11 +1,60 @@ -/** +/*! * Off-Canvas Sidebars plugin * * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3 + * @version 0.4 + * @preserve + */ + +/** + * Slidebar CSS overwrites */ +/* @fixme Fix overlay issues with shift and reveal on pages not that don't have full height, currently done in JS window resize. */ +html, +html.ocs-initialized { + overflow-y: auto; + height: auto; +} +[canvas=container], +.ocs-initialized [canvas=container] { + overflow-y: hidden; + height: auto; +} + + +/*[canvas-fixed] { + -webkit-transform: translate( 0px, 0px ); + -moz-transform: translate( 0px, 0px ); + -ms-transform: translate( 0px, 0px ); + -o-transform: translate( 0px, 0px ); + transform: translate( 0px, 0px ); + -webkit-backface-visibility: hidden; +}*/ + +.ocs-legacy [canvas] {top: 0; right: 0; bottom: 0; left: 0;} +.ocs-legacy [canvas], +.ocs-legacy [off-canvas] { + -webkit-transform: none; + -moz-transform: none; + -ms-transform: none; + -o-transform: none; + transform: none; + -webkit-transition: -webkit-transform 300ms, top 300ms, bottom 300ms, left 300ms, right 300ms; + -moz-transition: -moz-transform 300ms, top 300ms, bottom 300ms, left 300ms, right 300ms; + -o-transition: -o-transform 300ms, top 300ms, bottom 300ms, left 300ms, right 300ms; + transition: transform 300ms, top 300ms, bottom 300ms, left 300ms, right 300ms; +} + +/* @todo fix support for top and bottom */ +[off-canvas*=" top"][off-canvas*=" reveal"], +[off-canvas*=" top"][off-canvas*=" shift"], +[off-canvas*=" bottom"][off-canvas*=" reveal"], +[off-canvas*=" bottom"][off-canvas*=" shift"] { + z-index: 1; +} + /** * Sidebar Widths (patched from older version of Slidebars) */ diff --git a/css/off-canvas-sidebars.min.css b/css/off-canvas-sidebars.min.css new file mode 100644 index 0000000..e7fb711 --- /dev/null +++ b/css/off-canvas-sidebars.min.css @@ -0,0 +1,9 @@ +/*! + * Off-Canvas Sidebars plugin + * + * @author Jory Hogeveen + * @package off-canvas-sidebars + * @version 0.4 + * @preserve + */ +html,html.ocs-initialized{overflow-y:auto;height:auto}[canvas=container],.ocs-initialized [canvas=container]{overflow-y:hidden;height:auto}.ocs-legacy [canvas]{top:0;right:0;bottom:0;left:0}.ocs-legacy [canvas],.ocs-legacy [off-canvas]{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:-webkit-transform 300ms,top 300ms,bottom 300ms,left 300ms,right 300ms,clip-path 0;-moz-transition:-moz-transform 300ms,top 300ms,bottom 300ms,left 300ms,right 300ms,clip-path 0;-o-transition:-o-transform 300ms,top 300ms,bottom 300ms,left 300ms,right 300ms,clip-path 0;transition:transform 300ms,top 300ms,bottom 300ms,left 300ms,right 300ms,clip-path 0}[off-canvas*=" top"][off-canvas*=" reveal"],[off-canvas*=" top"][off-canvas*=" shift"],[off-canvas*=" bottom"][off-canvas*=" reveal"],[off-canvas*=" bottom"][off-canvas*=" shift"]{z-index:1}.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:30%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:15%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:45%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:30%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:15%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:45%}@media(max-width:480px){.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:60%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:35%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:85%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:40%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:20%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:60%}}@media(min-width:481px){.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:50%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:30%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:70%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:40%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:20%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:60%}}@media(min-width:768px){.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:40%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:25%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:55%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:35%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:20%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:55%}}@media(min-width:992px){.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:30%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:15%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:45%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:30%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:15%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:45%}}@media(min-width:1200px){.ocs-size-default.ocs-location-left,.ocs-size-default.ocs-location-right{width:25%}.ocs-size-small.ocs-location-left,.ocs-size-small.ocs-location-right{width:10%}.ocs-size-large.ocs-location-left,.ocs-size-large.ocs-location-right{width:40%}.ocs-size-default.ocs-location-top,.ocs-size-default.ocs-location-bottom{height:25%}.ocs-size-small.ocs-location-top,.ocs-size-small.ocs-location-bottom{height:10%}.ocs-size-large.ocs-location-top,.ocs-size-large.ocs-location-bottom{height:40%}} \ No newline at end of file diff --git a/includes/api.php b/includes/api.php new file mode 100644 index 0000000..e2c3f0e --- /dev/null +++ b/includes/api.php @@ -0,0 +1,151 @@ + + * @package off-canvas-sidebars + * @version 0.4 + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +/** + * Echos one, multiple or all OCS sidebars. + * + * @api + * @since 0.3 + * @param string|array $sidebars (Optional) The ID of this sidebar as configured in: Appearances > Off-Canvas Sidebars > Sidebars. + */ +function the_ocs_off_canvas_sidebar( $sidebars = '' ) { + $instance = off_canvas_sidebars_frontend(); + if ( $instance ) { + if ( empty( $sidebars ) ) { + $instance->do_sidebars(); + } else { + if ( is_array( $sidebars ) ) { + foreach ( $sidebars as $sidebar ) { + $instance->do_sidebar( (string) $sidebar ); + } + } else { + $instance->do_sidebar( (string) $sidebars ); + } + } + } +} + +/** + * Output a trigger element for off-canvas sidebars. + * + * @api + * @since 0.4 + * @param array $atts { + * Required array of arguments + * @type string id (Required) The off-canvas sidebar ID. + * @type string text The text to show. Default: ''. + * @type string action The trigger action. Default: `toggle`. + * @type string element The HTML element. Default: `button`. + * @type array|string class Add extra classes? Also accepts a string with classes separated with a space. + * @type array attr { + * Other attributes to add. Format: attribute name (array key) => attribute value + * } + * } + * @param string $content (Optional) HTML/text string. + * @return string + */ +function the_ocs_control_trigger( $atts, $content = '' ) { + $instance = off_canvas_sidebars_frontend(); + if ( $instance ) { + + if ( empty( $atts['id'] ) ) { + return __( 'No Off-Canvas Sidebar ID provided.', 'off-canvas-sidebars' ); + } + + $atts = shortcode_atts( array( + 'id' => false, + 'text' => '', // Text to show. + 'action' => 'toggle', // toggle|open|close + 'element' => 'button', // button|span|i|b|a|etc. + 'class' => array(), // Extra classes, also accepts a string with classes separated with a space. + 'attr' => array(), // An array of attribute keys and their values. + 'echo' => true, + ), $atts, 'ocs_trigger' ); + + $return = ''; + if ( ! empty( $content ) ) { + $atts['text'] = $content; + } + + $return = $instance->do_control_trigger( $atts['id'], $atts ) . $return; + if ( (boolean) $atts['echo'] ) { + echo $return; + } + return $return; + } + return ''; +} + +/** + * Shortcode handler for the_ocs_control_trigger(). + * + * Example 1 (simple shortcode with all options): + * [ocs_trigger id="left" action="open" element="a" button="1" text="My trigger button!" attr="href: #; rel: nofollow; alt: Yay!!"] + * + * Example 2 (nested shortcode with some options: + * [ocs_trigger id="right" attr="type:button;alt:Yay!!"]My trigger button text[/ocs_trigger] + * + * @since 0.4 + * @see the_ocs_control_trigger() for detailed info. + * @param array $atts + * @param string $content (Optional) HTML/text string. + * @return string + */ +function shortcode_ocs_trigger( $atts, $content = '' ) { + // Shortcodes don't echo. + $atts['echo'] = false; + + // You can also use `attributes` instead of `attr` for readability. If both are used, `attributes` is ignored. + if ( empty( $atts['attr'] ) && ! empty( $atts['attributes'] ) ) { + $atts['attr'] = $atts['attributes']; + } + unset( $atts['attributes'] ); + + // You can also use `classes` instead of `class` for readability. If both are used, `classes` is ignored. + if ( empty( $atts['class'] ) && ! empty( $atts['classes'] ) ) { + $atts['class'] = $atts['classes']; + } + unset( $atts['classes'] ); + + // Parse attributes send through the shortcode. + if ( ! empty( $atts['attr'] ) ) { + $attr = explode( ';', $atts['attr'] ); + $atts['attr'] = array(); + foreach ( $attr as $key => $value ) { + $attr[ $key ] = explode( ':', $value ); + if ( count( $attr[ $key ] ) > 1 ) { + $attribute = trim( $attr[ $key ][0] ); + unset( $attr[ $key ][0] ); + $atts['attr'][ $attribute ] = trim( implode( ':', $attr[ $key ] ) ); + } + } + } + + return the_ocs_control_trigger( $atts, $content ); +} +add_shortcode( 'ocs_trigger', 'shortcode_ocs_trigger' ); + +/** + * Main instance of Off-Canvas Sidebars Frontend. + * + * Returns the main instance of OCS_Off_Canvas_Sidebars_Frontend to prevent the need to use globals. + * + * @since 0.3 + * @return OCS_Off_Canvas_Sidebars_Frontend + */ +function off_canvas_sidebars_frontend() { + if ( is_callable( array( 'OCS_Off_Canvas_Sidebars_Frontend', 'get_instance' ) ) ) { + return OCS_Off_Canvas_Sidebars_Frontend::get_instance(); + } + return null; +} diff --git a/includes/class-editor-shortcode-generator.php b/includes/class-editor-shortcode-generator.php new file mode 100644 index 0000000..c20bb28 --- /dev/null +++ b/includes/class-editor-shortcode-generator.php @@ -0,0 +1,246 @@ + + * @package off-canvas-sidebars + * @version 0.4 + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +final class OCS_Off_Canvas_Sidebars_Editor_Shortcode_Generator +{ + /** + * The single instance of the class. + * + * @var OCS_Off_Canvas_Sidebars_Editor_Shortcode_Generator + * @since 0.4 + */ + protected static $_instance = null; + + private $settings = array(); + + /** + * This class gets called in the init hook. + * + * @since 0.4 + * @access private + */ + private function __construct() { + // Check user permissions. + /*if ( !current_user_can( 'edit_posts' ) && !current_user_can( 'edit_pages' ) ) { + return; + }*/ + + if ( 'true' === get_user_option( 'rich_editing' ) ) { + //add_action( 'admin_init', array( $this, 'load_plugin_data' ) ); + $this->load_plugin_data(); + add_action( 'media_buttons', array( $this, 'media_buttons' ), 20 ); + add_filter( 'mce_external_plugins', array( $this, 'mce_external_plugins' ) ); + add_filter( 'tiny_mce_before_init', array( $this, 'mce_inline_css' ) ); + add_action( 'after_wp_tiny_mce', array( $this, 'print_scripts' ) ); + } + } + + /** + * Get plugin defaults. + * @since 0.4 + */ + function load_plugin_data() { + $this->settings = off_canvas_sidebars()->get_settings(); + } + + /** + * Show our own button. + * + * @since 0.4 + * @param string $editor_id The Editor ID. + */ + function media_buttons( $editor_id ) { + //dashicons-move dashicons-editor-code +?> + +settings['sidebars'] as $sidebar_id => $sidebar_data ) { + if ( empty( $sidebar_data['enable'] ) ) { + continue; + } + $label = $sidebar_id; + if ( ! empty( $sidebar_data['label'] ) ) { + $label = $sidebar_data['label'] . ' (' . $sidebar_id . ')'; + } + $sidebars[] = array( + 'text' => $label, + 'value' => $sidebar_id, + ); + } + + $elements = array( 'button', 'span', 'a', 'b', 'strong', 'i', 'em', 'img', 'div' ); + $element_values = array(); + foreach ( $elements as $e ) { + $element_values[] = array( + 'text' => '<' . $e . '>', + 'value' => $e, + ); + } + + $fields = array( + 'id' => array( + 'type' => 'listbox', + 'name' => 'id', + 'label' => __( 'Sidebar ID', 'off-canvas-sidebars' ), + 'value' => '', + 'values' => $sidebars, + 'tooltip' => __( '(Required) The off-canvas sidebar ID', 'off-canvas-sidebars' ), + ), + 'text' => array( + 'type' => 'textbox', + 'name' => 'text', + 'label' => __( 'Text', 'off-canvas-sidebars' ), + 'value' => '', + 'tooltip' => __( 'Limited HTML allowed', 'off-canvas-sidebars' ), + 'multiline' => true, + ), + 'optional_container' => array( + 'type' => 'container', + 'html' => '' . __( 'Optional options', 'off-canvas-sidebars' ) . ':', + ), + 'action' => array( + 'type' => 'listbox', + 'name' => 'action', + 'label' => __( 'Trigger action', 'off-canvas-sidebars' ), + 'value' => '', + 'values' => array( + array( + 'text' => __( 'Toggle', 'off-canvas-sidebars' ) . ' (' . __( 'Default', 'off-canvas-sidebars' ) . ')', + 'value' => '', + ), + array( + 'text' => __( 'Open', 'off-canvas-sidebars' ), + 'value' => 'open', + ), + array( + 'text' => __( 'Close', 'off-canvas-sidebars' ), + 'value' => 'close', + ), + ), + //'tooltip' => __( 'The trigger action. Default: toggle', 'off-canvas-sidebars' ), + ), + 'element' => array( + 'type' => 'listbox', + 'name' => 'element', + 'label' => __( 'HTML element', 'off-canvas-sidebars' ), + 'value' => '', + 'values' => $element_values, + 'tooltip' => __( 'Choose wisely', 'off-canvas-sidebars' ), + ), + 'class' => array( + 'type' => 'textbox', + 'name' => 'class', + 'label' => __( 'Extra classes', 'off-canvas-sidebars' ), + 'value' => '', + 'tooltip' => __( 'Separate multiple classes with a space', 'off-canvas-sidebars' ), + ), + 'attr' => array( + 'type' => 'textbox', + 'name' => 'attr', + 'label' => __( 'Custom attributes', 'off-canvas-sidebars' ), + 'value' => '', + 'tooltip' => __( 'key : value ; key : value', 'off-canvas-sidebars' ), + 'multiline' => true, + ), + 'nested' => array( + 'type' => 'checkbox', + 'name' => 'nested', + 'label' => __( 'Nested shortcode', 'off-canvas-sidebars' ) . '?', + 'value' => '', + 'tooltip' => __( '[ocs_trigger text="Your text"] or [ocs_trigger]Your text[/ocs_trigger]', 'off-canvas-sidebars' ), + ), + ); +?> + + + * @package off-canvas-sidebars + * @version 0.4 + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +abstract class OCS_Off_Canvas_Sidebars_Form +{ + protected $general_key = ''; + protected $settings = array(); + protected $plugin_key = ''; + + /** + * Frontend type selecton + * @deprecated + * @param array $args + */ + function frontend_type_option( $args ) { + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + + $html = '
'; + $html .= ''; + $html .= ''; + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * Echo checkboxes to enable/disable sidebars outside the sidebars tab. + */ + function enabled_sidebars_option() { + $prefix_name = esc_attr( $this->general_key ) . '[sidebars]'; + $prefix_value = $this->settings['sidebars']; + $prefix_id = $this->general_key . '_sidebars'; + //$prefix_classes = array( $prefix_id ); + if ( ! empty( $this->settings['sidebars'] ) ) { + $html = '
'; + + foreach ( $prefix_value as $sidebar => $sidebar_data ) { + //$classes = $this->get_option_classes( $prefix_classes, 'enable' ); + $html .= ''; + } + $html .= ''; + $html .= '
'; + echo $html; + } else { + $tab = ( isset( $this->sidebars_tab ) ) ? '&tab=' . $this->sidebars_tab : ''; + echo '' + . esc_html__( 'Click here to add off-canvas sidebars', 'off-canvas-sidebars' ) . ''; + } + } + + /** + * The sidebars location option. + * @param array $args + */ + function sidebar_location( $args ) { + if ( ! isset( $args['sidebar'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + $classes = $this->get_option_classes( $prefix_classes, 'location' ); + + $html = '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * The sidebars size option. + * @param array $args + */ + function sidebar_size( $args ) { + if ( ! isset( $args['sidebar'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + $classes = $this->get_option_classes( $prefix_classes, 'size' ); + + $html = '
'; + $html .= ''; + $html .= ''; + $html .= ''; + + $html .= '
'; + $html .= ''; + + $attr = array( + 'type' => 'number', + 'name' => $prefix_name . '[size_input]', + 'class' => $this->get_option_classes( $prefix_classes, 'size_input' ), + 'id' => $prefix_id . '_size_input', + 'value' => $prefix_value['size_input'], + 'min' => 1, + 'max' => '', + 'step' => 1, + ); + $html .= '   '; + $html .= ''; + + $html .= '
'; + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * The sidebars style option. + * @param array $args + */ + function sidebar_style( $args ) { + if ( ! isset( $args['sidebar'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + $classes = $this->get_option_classes( $prefix_classes, 'style' ); + + $html = '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * General input fields. + * @param array $args + */ + function text_option( $args ) { + if ( ! isset( $args['name'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + if ( isset( $args['value'] ) ) { + $prefix_value[ $args['name'] ] = $args['value']; + } + $classes = $this->get_option_classes( $prefix_classes, $args['name'] ); + if ( ! empty( $args['class'] ) ) { + $classes .= ' ' . $args['class']; + } + + $html = '
'; + + $attr = array( + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'class' => $classes, + 'id' => $prefix_id . '_' . $args['name'], + ); + if ( isset( $args['placeholder'] ) ) { + $attr['placeholder'] = $args['placeholder']; + } + + if ( ! empty( $args['multiline'] ) ) { + $field = ''; + } else { + $attr['type'] = 'text'; + $attr['value'] = $prefix_value[ $args['name'] ]; + $field = ''; + } + if ( isset( $args['label'] ) ) { + $field = ''; + } + + $html .= $field; + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @param array $args + */ + function checkbox_option( $args ) { + if ( ! isset( $args['name'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + if ( isset( $args['value'] ) ) { + $prefix_value[ $args['name'] ] = $args['value']; + } + $classes = $this->get_option_classes( $prefix_classes, $args['name'] ); + + $html = '
'; + + $attr = array( + 'type' => 'checkbox', + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'class' => $classes, + 'id' => $prefix_id . '_' . $args['name'], + 'value' => 1, + ); + + $field = ''; + if ( isset( $args['label'] ) ) { + $field = ''; + } + $html .= $field; + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @param array $args + */ + function radio_option( $args ) { + if ( empty( $args['name'] ) || empty( $args['options'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + if ( isset( $args['value'] ) ) { + $prefix_value[ $args['name'] ] = $args['value']; + } + if ( ! empty( $args['default'] ) && empty( $prefix_value[ $args['name'] ] ) ) { + $prefix_value[ $args['name'] ] = $args['default']; + } + $classes = $this->get_option_classes( $prefix_classes, $args['name'] ); + + $html = '
'; + + foreach ( $args['options'] as $option ) { + + if ( ! isset( $prefix_value[ $args['name'] ] ) ) { + $prefix_value[ $args['name'] ] = ( isset( $args['value'] ) ) ? $args['value'] : false; + } + + $attr = array( + 'type' => 'radio', + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'class' => $classes, + 'id' => $prefix_id . '_' . $args['name'] . '_' . $option['name'], + 'value' => $option['value'], + ); + + $field = ''; + + if ( isset( $option['label'] ) ) { + $field = ''; + } + $field .= $this->do_description( $option , 'span' ); + $field .= '
'; + + $html .= $field; + + } // End foreach(). + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @param array $args + */ + function select_option( $args ) { + if ( empty( $args['name'] ) || empty( $args['options'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + if ( isset( $args['value'] ) ) { + $prefix_value[ $args['name'] ] = $args['value']; + } + if ( ! empty( $args['default'] ) && empty( $prefix_value[ $args['name'] ] ) ) { + $prefix_value[ $args['name'] ] = $args['default']; + } + $classes = $this->get_option_classes( $prefix_classes, $args['name'] ); + + $html = '
'; + + $attr = array( + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'class' => $classes, + 'id' => $prefix_id . '_' . $args['name'], + ); + + $html .= ''; + if ( isset( $args['label'] ) ) { + $html = '
'; + } + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @param array $args + */ + function number_option( $args ) { + if ( ! isset( $args['name'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + $classes = $this->get_option_classes( $prefix_classes, $args['name'] ); + + $attr = array( + 'type' => 'number', + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'class' => $classes, + 'id' => $prefix_id . '_' . $args['name'], + 'value' => $prefix_value[ $args['name'] ], + 'min' => 1, + 'max' => '', + 'step' => 1, + ); + $html = '
'; + + $field = ''; + if ( ! empty( $args['input_after'] ) ) { + $field .= ' ' . $args['input_after']; + } + if ( isset( $args['label'] ) ) { + $field = ''; + } + $html .= $field; + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @param array $args + */ + function color_option( $args ) { + if ( ! isset( $args['name'] ) ) { + return; + } + $prefixes = $this->get_option_prefixes( $args ); + $prefix_name = $prefixes['prefixName']; + $prefix_value = $prefixes['prefixValue']; + $prefix_id = $prefixes['prefixId']; + $prefix_classes = $prefixes['prefixClasses']; + + $classes = $this->get_option_classes( $prefix_classes, $args['name'] . '_type' ); + + $html = '
'; + + $html .= ' (' . esc_html__( 'Overwritable with CSS', 'off-canvas-sidebars' ) . ')
'; + $html .= '
'; + $html .= '
'; + + $html .= '
'; + $attr = array( + 'type' => 'text', + 'class' => 'color-picker ' . $this->get_option_classes( $prefix_classes, $args['name'] ), + 'id' => $prefix_id . '_' . $args['name'], + 'name' => $prefix_name . '[' . $args['name'] . ']', + 'value' => $prefix_value[ $args['name'] ], + ); + $html .= ''; + $html .= '
'; + + $html .= $this->do_description( $args ); + $html .= '
'; + echo $html; + } + + /** + * @since 0.4 + * @param array $args + * @param string $elem + * @return string + */ + function do_description( $args, $elem = 'p' ) { + if ( isset( $args['description'] ) ) { + return '<' . $elem . ' class="description">' . $args['description'] . ''; + } + return ''; + } + + /** + * Returns attribute prefixes for general settings and sidebar settings + * + * @since 0.1 + * + * @param array $args Arguments from the settings field + * @return array $prefixes Prefixes for name, value and id attributes + */ + function get_option_prefixes( $args ) { + if ( isset( $args['sidebar'] ) ) { + $prefix_name = esc_attr( $this->general_key ) . '[sidebars][' . $args['sidebar'] . ']'; + $prefix_value = $this->settings['sidebars'][ $args['sidebar'] ]; + $prefix_id = $this->general_key . '_sidebars_' . $args['sidebar']; + $prefix_classes = array( + $this->general_key . '_sidebars_' . $args['sidebar'], + $this->general_key . '_sidebars', + ); + } else { + $prefix_name = esc_attr( $this->general_key ); + $prefix_value = $this->settings; + $prefix_id = $this->general_key; + $prefix_classes = array( + $this->general_key, + ); + } + if ( ! empty( $args['required'] ) ) { + $prefix_classes[] = 'required'; + } + return array( + 'prefixName' => $prefix_name, + 'prefixValue' => $prefix_value, + 'prefixId' => $prefix_id, + 'prefixClasses' => $prefix_classes, + ); + } + + /** + * Combine classes prefixed with the field name + * @since 0.2 + * @param $classes + * @param $append + * @return string + */ + function get_option_classes( $classes, $append ) { + if ( $append ) { + foreach ( $classes as $key => $class ) { + if ( ! in_array( $class, array( 'required', 'widefat' ), true ) ) + $classes[ $key ] = $class . '_' . $append; + } + } + return implode( ' ', $classes ); + } + + /** + * Merge two arrays of attributes into one, combining values. + * It currently doesn't convert variable types. + * + * @since 0.4 + * @static + * + * @param array $attr The current attributes. + * @param array $new The new attributes. Attribute names as key. + * @return array + */ + public static function merge_attr( $attr, $new ) { + foreach ( $new as $key => $value ) { + if ( empty( $attr[ $key ] ) ) { + $attr[ $key ] = $value; + continue; + } + if ( is_array( $attr[ $key ] ) ) { + $attr[ $key ] = array_merge( $attr[ $key ], (array) $value ); + continue; + } + if ( is_array( $value ) ) { + $value = implode( ' ', $value ); + } + $attr[ $key ] .= ( ! empty( $value ) ) ? ' ' . $value : ''; + } + return $attr; + } + + /** + * Converts an array of attributes to a HTML string format starting with a space. + * + * @since 0.4 + * @static + * + * @param array $array Array to parse. (attribute => value pairs) + * @return string + */ + public static function parse_to_html_attr( $array ) { + $str = ''; + if ( is_array( $array ) && ! empty( $array ) ) { + foreach ( $array as $attr => $value ) { + if ( is_array( $value ) ) { + $value = implode( ' ', $value ); + } + $array[ $attr ] = esc_attr( $attr ) . '="' . esc_attr( $value ) . '"'; + } + $str = implode( ' ', $array ); + } + return $str; + } + +} // end class diff --git a/includes/off-canvas-sidebars-frontend.class.php b/includes/class-frontend.php similarity index 56% rename from includes/off-canvas-sidebars-frontend.class.php rename to includes/class-frontend.php index 9b3c847..c3b8f79 100644 --- a/includes/off-canvas-sidebars-frontend.class.php +++ b/includes/class-frontend.php @@ -2,13 +2,14 @@ /** * Off-Canvas Sidebars plugin front-end * - * Front-end * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3.1 + * @version 0.4 */ -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); +if ( ! defined( 'ABSPATH' ) ) { + die(); +} final class OCS_Off_Canvas_Sidebars_Frontend { @@ -20,7 +21,7 @@ final class OCS_Off_Canvas_Sidebars_Frontend */ protected static $_instance = null; - private $general_settings = array(); + private $settings = array(); /** * @since 0.3 private constructor @@ -29,7 +30,7 @@ final class OCS_Off_Canvas_Sidebars_Frontend private function __construct() { $this->load_plugin_data(); - if ( $this->general_settings['enable_frontend'] == true ) { + if ( $this->settings['enable_frontend'] ) { $this->default_actions(); } @@ -38,14 +39,30 @@ private function __construct() { add_action( 'wp_enqueue_scripts', array( $this, 'add_styles_scripts' ) ); //add_action( 'wp_footer', array( $this, 'add_inline_scripts' ), 999999999 ); // enforce last addition add_action( 'wp_head', array( $this, 'add_inline_styles' ) ); + + add_filter( 'body_class', array( $this, 'filter_body_class' ) ); } /** * Get plugin defaults + * @since 0.1 */ private function load_plugin_data() { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $this->general_settings = $off_canvas_sidebars->get_settings(); + $this->settings = off_canvas_sidebars()->get_settings(); + } + + /** + * Add classes to the body + * + * @since 1.4 + * @param array $classes + * @return array + */ + public function filter_body_class( $classes ) { + if ( 'legacy-css' === $this->settings['compatibility_position_fixed'] ) { + $classes[] = 'ocs-legacy'; + } + return $classes; } /** @@ -56,10 +73,10 @@ private function load_plugin_data() { */ private function default_actions() { - $before_hook = trim( $this->general_settings['website_before_hook'] ); - $after_hook = trim( $this->general_settings['website_after_hook'] ); + $before_hook = trim( $this->settings['website_before_hook'] ); + $after_hook = trim( $this->settings['website_after_hook'] ); - if ( get_template() == 'genesis' ) { + if ( 'genesis' === get_template() ) { $before_hook = 'genesis_before'; $after_hook = 'genesis_after'; } @@ -96,10 +113,10 @@ function before_site() { do_action( 'ocs_container_before' ); $atts = array( - 'ocs-site_close' => ( $this->general_settings['site_close'] ) ? true : false, - 'ocs-disable_over' => ( $this->general_settings['disable_over'] ) ? (int) $this->general_settings['disable_over'] : false, - 'ocs-hide_control_classes' => ( $this->general_settings['hide_control_classes'] ) ? true : false, - 'ocs-scroll_lock' => ( $this->general_settings['scroll_lock'] ) ? true : false, + 'ocs-site_close' => ( $this->settings['site_close'] ) ? true : false, + 'ocs-disable_over' => ( $this->settings['disable_over'] ) ? (int) $this->settings['disable_over'] : false, + 'ocs-hide_control_classes' => ( $this->settings['hide_control_classes'] ) ? true : false, + 'ocs-scroll_lock' => ( $this->settings['scroll_lock'] ) ? true : false, ); foreach ( $atts as $name => $value ) { @@ -109,7 +126,7 @@ function before_site() { $atts[ $name ] = $name . '="' . $value . '"'; } - echo '
'; + echo '
'; // Add content before other content in the site container do_action( 'ocs_container_inner_before' ); @@ -127,7 +144,7 @@ function after_site() { // Add content after other content in the site container do_action( 'ocs_container_inner_after' ); - if ( $this->general_settings['frontend_type'] != 'jquery' ) { + if ( 'jquery' !== $this->settings['frontend_type'] ) { echo '
'; // close #ocs-site } // Add content after the site container @@ -147,7 +164,7 @@ function after_site_script() { ?> general_settings['sidebars'] ) ) { - foreach ( $this->general_settings['sidebars'] as $sidebar => $sidebar_data ) { - if ( ! empty( $sidebar_data['enable'] ) ) { - $this->do_sidebar( $sidebar ); - } + if ( ! empty( $this->settings['sidebars'] ) ) { + foreach ( $this->settings['sidebars'] as $sidebar_id => $sidebar_data ) { + $this->do_sidebar( $sidebar_id ); } } } @@ -175,15 +190,20 @@ function do_sidebars() { * Echos a sidebar * * @since 0.1 + * @param string $sidebar_id * @return void * @access public */ function do_sidebar( $sidebar_id ) { - if ( ! empty( $this->general_settings['sidebars'][ $sidebar_id ] ) ) { + if ( ! empty( $this->settings['sidebars'][ $sidebar_id ] ) ) { + + $sidebar_data = $this->settings['sidebars'][ $sidebar_id ]; - $sidebar_data = $this->general_settings['sidebars'][ $sidebar_id ]; + if ( empty( $sidebar_data['enable'] ) ) { + return; + } - echo '
get_sidebar_attributes( $sidebar_id, $sidebar_data ) . '>'; + echo '
get_sidebar_attributes( $sidebar_id, $sidebar_data ) . '>'; /** * Action to add content before the default sidebar content @@ -197,20 +217,20 @@ function do_sidebar( $sidebar_id ) { */ do_action( 'ocs_custom_content_sidebar_before', $sidebar_id, $sidebar_data ); - if ( 'sidebar' == $sidebar_data['content'] ) { + if ( 'sidebar' === $sidebar_data['content'] ) { - if ( get_template() == 'genesis' ) { + if ( 'genesis' === get_template() ) { genesis_widget_area( 'off-canvas-' . $sidebar_id );//, array('before'=>'')); } else { dynamic_sidebar( 'off-canvas-' . $sidebar_id );//, array('before'=>'')); } } - elseif( 'menu' == $sidebar_data['content'] ) { + elseif ( 'menu' === $sidebar_data['content'] ) { $args = array( 'fallback_cb' => false, - 'container' => 'nav' // HTML5 FTW! + 'container' => 'nav', // HTML5 FTW! ); /** @@ -237,7 +257,7 @@ function do_sidebar( $sidebar_id ) { wp_nav_menu( $args ); } - elseif( 'action' == $sidebar_data['content'] ) { + elseif ( 'action' === $sidebar_data['content'] ) { /** * Action to hook into the sidebar content @@ -250,7 +270,7 @@ function do_sidebar( $sidebar_id ) { * @param array $sidebar_data The sidebar settings */ do_action( 'ocs_custom_content_sidebar_' . $sidebar_id, $sidebar_id, $sidebar_data ); - } + } // End if(). /** * Action to add content after the default sidebar content @@ -265,7 +285,7 @@ function do_sidebar( $sidebar_id ) { do_action( 'ocs_custom_content_sidebar_after', $sidebar_id, $sidebar_data ); echo '
'; - } + } // End if(). } /** @@ -273,17 +293,19 @@ function do_sidebar( $sidebar_id ) { * * @since 0.1 * @since 0.3 Overwrite global setting attributes + * @param string $sidebar_id + * @param array $data * @return string */ - function get_sidebar_attributes( $sidebar, $data ) { - $prefix = $this->general_settings['css_prefix']; + function get_sidebar_attributes( $sidebar_id, $data ) { + $prefix = $this->settings['css_prefix']; $atts = array(); $atts['class'] = array(); $atts['class'][] = $prefix . '-slidebar'; - $atts['class'][] = $prefix . '-' . esc_attr( $sidebar ); + $atts['class'][] = $prefix . '-' . esc_attr( $sidebar_id ); $atts['class'][] = 'ocs-slidebar'; - $atts['class'][] = 'ocs-' . esc_attr( $sidebar ); + $atts['class'][] = 'ocs-' . esc_attr( $sidebar_id ); $atts['class'][] = 'ocs-size-' . esc_attr( $data['size'] ); $atts['class'][] = 'ocs-location-' . esc_attr( $data['location'] ); $atts['class'][] = 'ocs-style-' . esc_attr( $data['style'] ); @@ -299,15 +321,15 @@ function get_sidebar_attributes( $sidebar, $data ) { * @param string $sidebar_id The ID of this sidebar as configured in: Appearances > Off-Canvas Sidebars > Sidebars * @param array $sidebar_data The sidebar settings */ - $atts['class'] = apply_filters( 'ocs_sidebar_classes', $atts['class'], $sidebar, $data ); + $atts['class'] = apply_filters( 'ocs_sidebar_classes', $atts['class'], $sidebar_id, $data ); // Slidebars 2.0 $atts['off-canvas'] = array( - $prefix . '-' . esc_attr( $sidebar ), // ID + $prefix . '-' . esc_attr( $sidebar_id ), // ID esc_attr( $data['location'] ), // Location - esc_attr( $data['style'] ) // Animation style + esc_attr( $data['style'] ), // Animation style ); - $atts['ocs-sidebar-id'] = esc_attr( $sidebar ); + $atts['ocs-sidebar-id'] = esc_attr( $sidebar_id ); // Overwrite global settings if ( true === (bool) $data['overwrite_global_settings'] ) { @@ -330,6 +352,98 @@ function get_sidebar_attributes( $sidebar, $data ) { return $return; } + /** + * Generate a trigger element + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @todo Refactor to enable above checks? + * + * @since 0.4 + * @param string $sidebar_id + * @param array $args see API: the_ocs_control_trigger() for info + * @return string + */ + public function do_control_trigger( $sidebar_id, $args = array() ) { + + $sidebar_id = (string) $sidebar_id; + + $defaults = array( + 'text' => '', // Text to show + 'action' => 'toggle', // toggle|open|close + 'element' => 'button', // button|span|i|b|a|etc. + 'class' => array(), // Extra classes (space separated), also accepts an array of classes + 'attr' => array(), // An array of attribute keys and their values + ); + $args = array_merge( $defaults, $args ); + + if ( in_array( $args['element'], array( 'base', 'body', 'html', 'link', 'meta', 'noscript', 'style', 'script', 'title' ), true ) ) { + return '' . __( 'This element is not supported for use as a button', 'off-canvas-sidebars' ) . ''; + } + + $singleton = false; + + // Is it a singleton element? Add the text to the attributes + if ( in_array( $args['element'], array( 'br', 'hr', 'img', 'input' ), true ) ) { + $singleton = true; + if ( 'img' === $args['element'] && empty( $args['attr']['alt'] ) ) { + $args['attr']['alt'] = $args['text']; + } + if ( 'input' === $args['element'] && empty( $args['attr']['value'] ) ) { + $args['attr']['value'] = $args['text']; + } + } + + $attr = ''; + if ( empty( $args['attr']['class'] ) ) { + $args['attr']['class'] = array(); + } + foreach ( $args['attr'] as $key => $value ) { + if ( 'class' === $key ) { + // Add our own classes + $ocs_classes = array( + $this->settings['css_prefix'] . '-trigger', + $this->settings['css_prefix'] . '-' . $args['action'], + $this->settings['css_prefix'] . '-' . $args['action'] . '-' . $sidebar_id, + ); + if ( ! is_array( $value ) ) { + $value = explode( ' ', $value ); + } + foreach ( $ocs_classes as $class ) { + if ( ! in_array( $class, $value, true ) ) { + $value[] = $class; + } + } + + // Optionally add extra classes + if ( ! empty( $args['class'] ) ) { + if ( ! is_array( $args['class'] ) ) { + $args['class'] = explode( ' ', $args['class'] ); + } + foreach ( $args['class'] as $c ) { + $c = esc_attr( $c ); + if ( ! in_array( $c, $value, true ) ) { + $value[] = $c; + } + } + } + } + if ( is_array( $value ) ) { + $value = implode( ' ', $value ); + } + $attr .= ' ' . esc_attr( $key ) . '="' . esc_attr( (string) $value ) . '"'; + } + + $return = '<' . $args['element'] . $attr; + if ( $singleton ) { + $return .= ' />'; + } else { + $return .= '>' . $args['text'] . ''; + } + + return $return; + } + /** * Add necessary scripts and styles * @@ -339,30 +453,42 @@ function get_sidebar_attributes( $sidebar, $data ) { * @return void */ function add_styles_scripts() { - $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; - $version = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? time() : OCS_PLUGIN_VERSION; - wp_enqueue_style( 'slidebars', OCS_PLUGIN_URL . 'slidebars/slidebars'.$suffix.'.css', array(), '2.0.2' ); - wp_enqueue_script( 'slidebars', OCS_PLUGIN_URL . 'slidebars/slidebars'.$suffix.'.js', array( 'jquery' ), '2.0.2', true ); + // @todo Validate and use minified files + $suffix = '';//defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; + $version = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? time() : OCS_PLUGIN_VERSION; - wp_enqueue_style( 'off-canvas-sidebars', OCS_PLUGIN_URL . 'css/off-canvas-sidebars.css', array(), $version ); // @todo: '.$suffix.' - wp_enqueue_script( 'off-canvas-sidebars', OCS_PLUGIN_URL . 'js/off-canvas-sidebars.js', array( 'jquery', 'slidebars' ), $version, true ); // @todo: '.$suffix.' - wp_localize_script( 'off-canvas-sidebars', 'ocsOffCanvasSidebars', array( - 'site_close' => ( $this->general_settings['site_close'] ) ? true : false, - 'disable_over' => ( $this->general_settings['disable_over'] ) ? (int) $this->general_settings['disable_over'] : false, - 'hide_control_classes' => ( $this->general_settings['hide_control_classes'] ) ? true : false, - 'scroll_lock' => ( $this->general_settings['scroll_lock'] ) ? true : false, - 'css_prefix' => $this->general_settings['css_prefix'], - 'sidebars' => $this->general_settings['sidebars'] - ) ); + // FastClick library https://github.com/ftlabs/fastclick + if ( $this->settings['use_fastclick'] ) { + wp_enqueue_script( 'fastclick', OCS_PLUGIN_URL . 'js/fastclick' . $suffix . '.js', array(), false, true ); + } - if ( true === (bool) $this->general_settings['compatibility_position_fixed'] ) { - wp_enqueue_script( 'ocs-fixed-scrolltop', OCS_PLUGIN_URL . 'js/fixed-scrolltop.js', array( 'jquery' ), $version, true ); + if ( 'custom-js' === $this->settings['compatibility_position_fixed'] ) { + wp_enqueue_script( 'ocs-fixed-scrolltop', OCS_PLUGIN_URL . 'js/fixed-scrolltop' . $suffix . '.js', array( 'jquery' ), $version, true ); } - // FastClick library https://github.com/ftlabs/fastclick - if ( true === (bool) $this->general_settings['use_fastclick'] ) { - wp_enqueue_script( 'fastclick', OCS_PLUGIN_URL . 'js/fastclick.js', array(), false, true ); + wp_enqueue_style( 'slidebars', OCS_PLUGIN_URL . 'slidebars/slidebars' . $suffix . '.css', array(), '2.0.2' ); + wp_enqueue_script( 'slidebars', OCS_PLUGIN_URL . 'slidebars/slidebars' . $suffix . '.js', array( 'jquery' ), '2.0.2', true ); + + wp_enqueue_style( 'off-canvas-sidebars', OCS_PLUGIN_URL . 'css/off-canvas-sidebars' . $suffix . '.css', array(), $version ); + wp_enqueue_script( 'off-canvas-sidebars', OCS_PLUGIN_URL . 'js/off-canvas-sidebars' . $suffix . '.js', array( 'jquery', 'slidebars' ), $version, true ); + + $sidebars = array(); + foreach ( $this->settings['sidebars'] as $sidebar_id => $sidebar_data ) { + if ( ! empty( $sidebar_data['enable'] ) ) { + $sidebars[ $sidebar_id ] = $sidebar_data; + } } + wp_localize_script( 'off-canvas-sidebars', 'ocsOffCanvasSidebars', array( + 'site_close' => (bool) $this->settings['site_close'], + 'disable_over' => ( $this->settings['disable_over'] ) ? (int) $this->settings['disable_over'] : false, + 'hide_control_classes' => (bool) $this->settings['hide_control_classes'], + 'scroll_lock' => (bool) $this->settings['scroll_lock'], + 'legacy_css' => (bool) ( 'legacy-css' === $this->settings['compatibility_position_fixed'] ), + 'fixed_elements' => $this->settings['fixed_elements'], + 'css_prefix' => $this->settings['css_prefix'], + 'sidebars' => $sidebars, + '_debug' => (bool) ( defined( 'WP_DEBUG' ) && WP_DEBUG ), + ) ); } /** @@ -384,43 +510,47 @@ function add_inline_scripts() { /** * Add inline styles * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @todo Refactor to enable above checks? + * * @since 0.1 * @return void */ function add_inline_styles() { if ( ! is_admin() ) { - $prefix = $this->general_settings['css_prefix']; + $prefix = $this->settings['css_prefix']; ?> + * @package off-canvas-sidebars + * @version 0.4 + * + * Credits to the Polylang plugin. + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +final class OCS_Off_Canvas_Sidebars_Menu_Meta_Box +{ + /** + * The single instance of the class. + * + * @var OCS_Off_Canvas_Sidebars_Menu_Meta_box + * @since 0.3 + */ + protected static $_instance = null; + + protected $meta_key = '_off_canvas_control_menu_item'; + + private $general_key = ''; + private $plugin_key = ''; + //private $plugin_tabs = array(); + private $settings = array(); + private $general_labels = array(); + private $link_classes = array( + '-trigger', + '-toggle', + // -toggle- + ); + + /** + * @since 0.3 private constructor + * @access private + */ + private function __construct() { + //add_action( 'admin_init', array( $this, 'load_settings' ) ); + add_action( 'init', array( $this, 'load_plugin_data' ) ); + add_action( 'admin_init', array( $this, 'add_meta_box' ), 11 ); + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 2 ); + add_filter( 'wp_get_nav_menu_items', array( $this, 'wp_get_nav_menu_items' ), 20 ); // after the customizer menus + } + + /** + * Get plugin defaults + */ + function load_plugin_data() { + $off_canvas_sidebars = off_canvas_sidebars(); + $this->settings = $off_canvas_sidebars->get_settings(); + $this->general_labels = $off_canvas_sidebars->get_general_labels(); + $this->general_key = $off_canvas_sidebars->get_general_key(); + $this->plugin_key = $off_canvas_sidebars->get_plugin_key(); + + foreach ( $this->link_classes as $key => $class ) { + $this->link_classes[ $key ] = $this->settings['css_prefix'] . $class; + } + } + + function add_meta_box() { + add_meta_box( + $this->plugin_key . '-meta-box', + esc_html__( 'Off-Canvas Control', 'off-canvas-sidebars' ), + array( $this, 'meta_box' ), + 'nav-menus', + 'side', + 'low' + ); + } + + function meta_box() { + global $_nav_menu_placeholder; //, $nav_menu_selected_id; + $off_canvas_sidebars = off_canvas_sidebars(); + $_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1; + ?> +
+
+
    + settings['sidebars'] as $sidebar => $sidebar_data ) { + if ( $sidebar_data['enable'] ) { + ?> +
  • + + + + + +
  • + is_sidebar_enabled() ) { + echo '
  • ' . $this->general_labels['no_sidebars_available'] . '
  • '; + } + ?> +
+
+ is_sidebar_enabled() ) { ?> +

+ + + + + + + +

+ +
+ base ) + return; + + $suffix = ''; //defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; + $version = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : OCS_PLUGIN_VERSION; + wp_enqueue_script( 'off_canvas_control_nav_menu', OCS_PLUGIN_URL . '/js/nav-menu' . $suffix . '.js', array( 'jquery' ), $version ); + + $data['strings'] = array( + 'show_icon' => __( 'Show icon', 'off-canvas-sidebars' ), + 'icon' => __( 'Icon classes', 'off-canvas-sidebars' ), + 'menu_item_type' => __( 'Off-Canvas Control', 'off-canvas-sidebars' ), + 'no_sidebars_available' => $this->general_labels['no_sidebars_available'], + ); + $data['controls'] = array(); + foreach ( $this->settings['sidebars'] as $sidebar => $sidebar_data ) { + if ( $sidebar_data['enable'] ) { + $data['controls'][ $sidebar ] = $sidebar_data['label']; + } + } + + // get all language switcher menu items + $items = get_posts( array( + 'numberposts' => -1, + 'nopaging' => true, + 'post_type' => 'nav_menu_item', + 'fields' => 'ids', + 'meta_key' => $this->meta_key, + ) ); + + // the options values for the triggers. + $data['val'] = array(); + foreach ( $items as $item ) + $data['val'][ $item ] = get_post_meta( $item, $this->meta_key, true ); + + // send all these data to javascript + wp_localize_script( 'off_canvas_control_nav_menu', 'ocsNavControl', $data ); + } + + /* + * save our menu item options + * + * @since 0.1 + * + * @param int $menu_id not used + * @param int $menu_item_db_id + */ + public function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0 ) { + $off_canvas_sidebars = off_canvas_sidebars(); + + // @codingStandardsIgnoreLine + if ( empty( $_POST['menu-item-url'][ $menu_item_db_id ] ) || '#off_canvas_control' !== $_POST['menu-item-url'][ $menu_item_db_id ] ) + return; + + // Security check since 'wp_update_nav_menu_item' can be called from outside WP admin. + if ( ! current_user_can( 'edit_theme_options' ) ) { + return; + } + + check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' ); + + $available_controls = array(); + foreach ( $this->settings['sidebars'] as $sidebar => $sidebar_data ) { + $available_controls[ $sidebar ] = $sidebar_data['label']; + } + + // Auto select control when adding a new item. + $default_control = ''; + if ( in_array( $_POST['menu-item-title'][ $menu_item_db_id ], $available_controls, true ) ) { + $default_control = $off_canvas_sidebars->get_sidebar_key_by_label( $_POST['menu-item-title'][ $menu_item_db_id ] ); + } + // default values. + $options = array( 'off-canvas-control' => $default_control ); + + // Our jQuery form has not been displayed. + if ( empty( $_POST['menu-item-off-canvas-control-detect'][ $menu_item_db_id ] ) ) { + + // Our options were never saved. + if ( ! get_post_meta( $menu_item_db_id, $this->meta_key, true ) ) { + update_post_meta( $menu_item_db_id, $this->meta_key, $options ); + } + + } else { + + $options['off-canvas-control'] = ''; + + // If only one is available, always select it. + if ( ! empty( $_POST['menu-item-off-canvas-control'][ $menu_item_db_id ] ) && + array_key_exists( $_POST['menu-item-off-canvas-control'][ $menu_item_db_id ], $available_controls ) + ) { + $options['off-canvas-control'] = strip_tags( stripslashes( $_POST['menu-item-off-canvas-control'][ $menu_item_db_id ] ) ); + } + + // Allow us to easily identify our nav menu item. + update_post_meta( $menu_item_db_id, $this->meta_key, $options ); + } + } + + /* + * Splits the one item of backend in several items on frontend. + * Takes care to menu_order as it is used later in wp_nav_menu. + * + * @since 0.1 + * + * @param array $items menu items + * @return array modified items + */ + public function wp_get_nav_menu_items( $items ) { + + if ( function_exists( 'doing_action' ) && doing_action( 'customize_register' ) || is_admin() ) { + // Needed since WP 4.3, doing_action available since WP 3.9. + return $items; + } + + foreach ( $items as $key => $item ) { + $options = get_post_meta( $item->ID, $this->meta_key, true ); + if ( ! $options ) { + continue; + } + $item->url = ''; + if ( isset( $this->settings['sidebars'][ $options['off-canvas-control'] ] ) && + $this->settings['sidebars'][ $options['off-canvas-control'] ]['enable'] + ) { + + $link_classes = $this->link_classes; + if ( ! is_array( $link_classes ) ) { + $link_classes = explode( ' ', (string) $link_classes ); + } + + if ( ! empty( $options['off-canvas-control'] ) ) { + $link_classes[] = $this->settings['css_prefix'] . '-toggle-' . $options['off-canvas-control']; + } + + if ( ! is_array( $item->classes ) ) { + $item->classes = explode( ' ', $item->classes ); + } + + $item->classes = array_merge( $item->classes, $link_classes ); + } + } + + return $items; + } + + /** + * Main Off-Canvas Sidebars Menu Meta Box Instance. + * + * Ensures only one instance of this class is loaded or can be loaded. + * + * @since 0.3 + * @static + * @return OCS_Off_Canvas_Sidebars_Menu_Meta_box + */ + public static function get_instance() { + if ( is_null( self::$_instance ) ) { + self::$_instance = new self(); + } + return self::$_instance; + } + +} // end class diff --git a/includes/class-settings.php b/includes/class-settings.php new file mode 100644 index 0000000..e840b5f --- /dev/null +++ b/includes/class-settings.php @@ -0,0 +1,1348 @@ + + * @package off-canvas-sidebars + * @version 0.4 + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +final class OCS_Off_Canvas_Sidebars_Settings extends OCS_Off_Canvas_Sidebars_Form +{ + /** + * The single instance of the class. + * + * @var OCS_Off_Canvas_Sidebars_Settings + * @since 0.3 + */ + protected static $_instance = null; + + protected $general_key = ''; + protected $settings_tab = 'ocs-settings'; + protected $sidebars_tab = 'ocs-sidebars'; + protected $shortcode_tab = 'ocs-shortcode'; + protected $importexport_tab = 'ocs-importexport'; + protected $plugin_key = ''; + protected $plugin_tabs = array(); + protected $settings = array(); + protected $general_labels = array(); + protected $capability = 'edit_theme_options'; + protected $post_tab = ''; + protected $tab = ''; + + /** + * @since 0.1 + * @since 0.3 Private constructor. + * @access private + */ + private function __construct() { + // @codingStandardsIgnoreStart + $this->post_tab = ( isset( $_POST['ocs_tab'] ) ) ? $_POST['ocs_tab'] : ''; + $this->tab = ( isset( $_GET['tab'] ) ) ? $_GET['tab'] : $this->settings_tab; + // @codingStandardsIgnoreEnd + $this->plugin_key = off_canvas_sidebars()->get_plugin_key(); + add_action( 'admin_init', array( $this, 'load_plugin_data' ) ); + add_action( 'admin_init', array( $this, 'register_settings' ) ); + add_action( 'admin_init', array( $this, 'maybe_importexport_settings' ) ); + add_action( 'admin_menu', array( $this, 'add_admin_menus' ), 15 ); + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles_scripts' ) ); + } + + /** + * Get plugin defaults. + * @since 0.1 + */ + public function load_plugin_data() { + $off_canvas_sidebars = off_canvas_sidebars(); + $this->settings = $off_canvas_sidebars->get_settings(); + $this->general_labels = $off_canvas_sidebars->get_general_labels(); + $this->general_key = $off_canvas_sidebars->get_general_key(); + + /** + * Change the capability for the OCS settings. + * @since 0.4 + * @param string + * @return string + */ + $this->capability = apply_filters( 'ocs_settings_capability', $this->capability ); + } + + /** + * Enqueue our styles and scripts only when it's our page. + * @since 0.1 + * @param string $hook + */ + public function enqueue_styles_scripts( $hook ) { + if ( 'appearance_page_' . $this->plugin_key !== $hook ) { + return; + } + + // Add the color picker css and script file. + wp_enqueue_style( 'wp-color-picker' ); + wp_enqueue_script( 'wp-color-picker' ); + wp_enqueue_script( 'postbox' ); + + // Add our own scripts. + wp_enqueue_style( 'off-canvas-sidebars-admin', OCS_PLUGIN_URL . '/css/off-canvas-sidebars-admin.css', array(), OCS_PLUGIN_VERSION ); + wp_enqueue_script( 'off-canvas-sidebars-settings', OCS_PLUGIN_URL . '/js/off-canvas-sidebars-settings.js', array( 'jquery' ), OCS_PLUGIN_VERSION, true ); + wp_localize_script( 'off-canvas-sidebars-settings', 'ocsOffCanvasSidebarsSettings', array( + 'general_key' => $this->general_key, + 'plugin_key' => $this->plugin_key, + 'css_prefix' => $this->settings['css_prefix'], + '__required_fields_not_set' => __( 'Some required fields are not set!', 'off-canvas-sidebars' ), + ) ); + + } + + /** + * Create admin page under the appearance menu. + * @since 0.1 + */ + public function add_admin_menus() { + add_theme_page( + esc_attr__( 'Off-Canvas Sidebars', 'off-canvas-sidebars' ), + esc_attr__( 'Off-Canvas Sidebars', 'off-canvas-sidebars' ), + $this->capability, + $this->plugin_key, + array( $this, 'plugin_options_page' ) + ); + } + + /** + * Register our settings. + * @since 0.1 + */ + public function register_settings() { + $this->plugin_tabs[ $this->settings_tab ] = esc_attr__( 'Settings', 'off-canvas-sidebars' ); + $this->plugin_tabs[ $this->sidebars_tab ] = esc_attr__( 'Sidebars', 'off-canvas-sidebars' ); + $this->plugin_tabs[ $this->shortcode_tab ] = esc_attr__( 'Shortcodes', 'off-canvas-sidebars' ); + + register_setting( $this->settings_tab, $this->general_key, array( $this, 'validate_input' ) ); + register_setting( $this->sidebars_tab, $this->general_key, array( $this, 'validate_input' ) ); + + add_settings_section( + 'section_general', + esc_attr__( 'Global Settings', 'off-canvas-sidebars' ), + '', + $this->settings_tab + ); + add_settings_section( + 'section_frontend', + esc_attr__( 'Frontend Settings', 'off-canvas-sidebars' ), + '', + $this->settings_tab + ); + add_settings_section( + 'section_admin', + esc_attr__( 'Admin Settings', 'off-canvas-sidebars' ), + '', + $this->settings_tab + ); + + $this->register_general_settings(); + + // Register sidebar settings. + foreach ( $this->settings['sidebars'] as $sidebar => $sidebar_data ) { + add_settings_section( + 'section_sidebar_' . $sidebar, + __( 'Off-Canvas Sidebar', 'off-canvas-sidebars' ) . ' - ' . $this->settings['sidebars'][ $sidebar ]['label'] . '', + array( $this, 'register_general_settings' ), + $this->sidebars_tab + ); + $this->register_sidebar_settings( $sidebar ); + } + + do_action( 'off_canvas_sidebar_settings' ); + } + + /** + * General settings. + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @todo Refactor to enable above checks? + * + * @since 0.1 + */ + private function register_general_settings() { + + /* + * General. + */ + add_settings_field( + 'enabled_sidebars', + esc_attr__( 'Enable Sidebars', 'off-canvas-sidebars' ), + array( $this, 'enabled_sidebars_option' ), + $this->settings_tab, + 'section_general' + ); + + /* + * Frontend. + */ + add_settings_field( + 'enable_frontend', + esc_attr__( 'Enable front-end', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'enable_frontend', + 'label' => __( 'Let this plugin add the necessary elements on the front-end.', 'off-canvas-sidebars' ), + // Translators: %s stands for a URL. + 'description' => sprintf( __( 'Read this to setup your theme for support! (Themes based on the Genesis Framework are supported by default)', 'off-canvas-sidebars' ), 'https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/theme-setup' ), + ) + ); + /*add_settings_field( + 'frontend_type', + esc_attr__( 'Front-end type', 'off-canvas-sidebars' ), + array( $this, 'frontend_type_option' ), + $this->settings_tab, + 'section_frontend' + );*/ + add_settings_field( + 'css_prefix', + esc_attr__( 'CSS Prefix', 'off-canvas-sidebars' ), + array( $this, 'text_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'css_prefix', + 'label' => __( 'Default', 'off-canvas-sidebars' ) . ': ocs', + 'placeholder' => 'ocs', + ) + ); + add_settings_field( + 'site_close', + esc_attr__( 'Close sidebar when clicking on the site', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'site_close', + 'label' => __( 'Enables closing of a off-canvas sidebar by clicking on the site. Default: true.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'disable_over', + esc_attr__( 'Disable over', 'off-canvas-sidebars' ), + array( $this, 'number_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'disable_over', + 'description' => __( 'Disable off-canvas sidebars over specified screen width. Leave blank to disable.', 'off-canvas-sidebars' ), + 'input_after' => 'px', + ) + ); + add_settings_field( + 'hide_control_classes', + esc_attr__( 'Auto-hide control classes', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'hide_control_classes', + 'label' => __( 'Hide off-canvas sidebar control classes over width specified in "Disable over". Default: false.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'scroll_lock', + esc_attr__( 'Scroll lock', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'scroll_lock', + 'label' => __( 'Prevent site content scrolling whilst a off-canvas sidebar is open. Default: false.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'background_color', + esc_attr__( 'Background color', 'off-canvas-sidebars' ), + array( $this, 'color_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'background_color', + 'description' => __( 'Choose a background color for the site container. Default: #ffffff.', 'off-canvas-sidebars' ), + ) + ); + // Genesis already has before and after hooks set. + if ( get_template() !== 'genesis' ) { + // Check if the before hook is filtered. If it is this setting is not needed. + if ( '' === apply_filters( 'ocs_website_before_hook', '' ) ) { + add_settings_field( + 'website_before_hook', + 'website_before ' . esc_attr__( 'hook name', 'off-canvas-sidebars' ), + array( $this, 'text_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'website_before_hook', + 'placeholder' => 'website_before', + ) + ); + } + // Check if the after hook is filtered. If it is this setting is not needed. + if ( '' === apply_filters( 'ocs_website_after_hook', '' ) ) { + add_settings_field( + 'website_after_hook', + 'website_after ' . esc_attr__( 'hook name', 'off-canvas-sidebars' ), + array( $this, 'text_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'website_after_hook', + 'placeholder' => 'website_after', + ) + ); + } + } + // https://github.com/ftlabs/fastclick + add_settings_field( + 'use_fastclick', + esc_attr__( 'Use the FastClick library?', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'use_fastclick', + 'label' => __( 'Yes. Default: disabled', 'off-canvas-sidebars' ), + 'description' => __( 'Devices with touch capability often have a 300ms delay on click triggers. FastClick is a JavaScript library purposely built to elimate the delay where neccesary.', 'off-canvas-sidebars' ), + ) + ); + + add_settings_field( + 'compatibility_position_fixed', + esc_attr__( 'Compatibility for fixed elements', 'off-canvas-sidebars' ), + array( $this, 'radio_option' ), + $this->settings_tab, + 'section_frontend', + array( + 'name' => 'compatibility_position_fixed', + 'default' => 'none', + 'options' => array( + 'none' => array( + 'name' => 'none', + 'label' => __( 'No', 'off-canvas-sidebars' ) . ' (' . __( 'Use CSS3 transform with hardware acceleration', 'off-canvas-sidebars' ) . ')', + 'value' => 'none', + 'description' => __( 'This is the default Slidebars behaviour.', 'off-canvas-sidebars' ), + ), + 'legacy-css' => array( + 'name' => 'legacy-css', + 'label' => __( 'Legacy CSS solution', 'off-canvas-sidebars' ) . ' (' . __( 'Use basic CSS positioning instead of CSS3 transform with hardware acceleration', 'off-canvas-sidebars' ) . ')', + 'value' => 'legacy-css', + 'description' => __( 'This is your best option if your site uses sticky menus and/or other fixed elements within the site container.', 'off-canvas-sidebars' ), + ), + 'custom-js' => array( + 'name' => 'custom-js', + 'label' => __( 'JavaScript solution', 'off-canvas-sidebars' ) . ' (' . __( 'Experimental', 'off-canvas-sidebars' ) . ')', + 'value' => 'custom-js', + 'description' => __( 'While still in development, this could fix compatibility issues with fixed elements.', 'off-canvas-sidebars' ), + ), + ), + ) + ); + + add_settings_field( + 'wp_editor_shortcode_rendering', + esc_attr__( 'Enable shortcode UI for the WordPress Editor?', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->settings_tab, + 'section_admin', + array( + 'name' => 'wp_editor_shortcode_rendering', + 'label' => __( 'Yes', 'off-canvas-sidebars' ) . ' (' . __( 'Experimental', 'off-canvas-sidebars' ) . ')', + 'description' => __( 'This will render the shortcodes to actual HTML elements in the WP Editor.', 'off-canvas-sidebars' ), + ) + ); + } + + /** + * Sidebar settings. + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @todo Refactor to enable above checks? + * + * @param string $sidebar_id + * @since 0.1 + */ + private function register_sidebar_settings( $sidebar_id ) { + + add_settings_field( + 'sidebar_enable', + esc_attr__( 'Enable', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'enable', + ) + ); + add_settings_field( + 'sidebar_id', + esc_attr__( 'ID', 'off-canvas-sidebars' ) . ' *', + array( $this, 'text_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'id', + 'value' => $sidebar_id, + 'required' => true, + 'description' => __( 'IMPORTANT: Must be unique!', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'sidebar_label', + esc_attr__( 'Name', 'off-canvas-sidebars' ), + array( $this, 'text_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'label', + ) + ); + add_settings_field( + 'sidebar_content', + esc_attr__( 'Content', 'off-canvas-sidebars' ), + array( $this, 'radio_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'content', + 'default' => 'sidebar', + 'options' => array( + 'sidebar' => array( + 'name' => 'sidebar', + 'label' => __( 'Sidebar', 'off-canvas-sidebars' ) . '   (' . __( 'Default', 'off-canvas-sidebars' ) . ')', + 'value' => 'sidebar', + ), + 'menu' => array( + 'name' => 'menu', + 'label' => __( 'Menu', 'off-canvas-sidebars' ), + 'value' => 'menu', + ), + 'action' => array( + 'name' => 'action', + 'label' => __( 'Custom', 'off-canvas-sidebars' ) . '   (' . __( 'Action hook', 'off-canvas-sidebars' ) . ': ocs_custom_content_sidebar_ )', + 'value' => 'action', + ), + ), + 'description' => __( 'Keep in mind that WordPress has menu and text widgets by default, the "sidebar" object is your best option in most cases.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'sidebar_location', + esc_attr__( 'Location', 'off-canvas-sidebars' ) . ' *', + array( $this, 'sidebar_location' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'required' => true, + ) + ); + add_settings_field( + 'sidebar_size', + esc_attr__( 'Size', 'off-canvas-sidebars' ), + array( $this, 'sidebar_size' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'description' => __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'sidebar_style', + esc_attr__( 'Style', 'off-canvas-sidebars' ) . ' *', + array( $this, 'sidebar_style' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'required' => true, + ) + ); + add_settings_field( + 'animation_speed', + esc_attr__( 'Animation speed', 'off-canvas-sidebars' ), + array( $this, 'number_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'animation_speed', + 'description' => + __( 'Set the animation speed for showing and hiding this sidebar. Default: 300ms', 'off-canvas-sidebars' ) . '
' . + __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), + 'input_after' => 'ms', + ) + ); + add_settings_field( + 'padding', + esc_attr__( 'Padding', 'off-canvas-sidebars' ), + array( $this, 'number_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'padding', + 'description' => + __( 'Add CSS padding (in pixels) to this sidebar. Default: none', 'off-canvas-sidebars' ) . '
' . + __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), + 'input_after' => 'px', + ) + ); + add_settings_field( + 'background_color', + esc_attr__( 'Background color', 'off-canvas-sidebars' ), + array( $this, 'color_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'background_color', + 'description' => + __( 'Choose a background color for this sidebar. Default: #222222.', 'off-canvas-sidebars' ) . '
' . + __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), + ) + ); + + add_settings_field( + 'overwrite_global_settings', + esc_attr__( 'Overwrite global settings', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'overwrite_global_settings', + ) + ); + add_settings_field( + 'site_close', + esc_attr__( 'Close sidebar when clicking on the site', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'site_close', + 'label' => __( 'Enables closing of a off-canvas sidebar by clicking on the site. Default: true.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'disable_over', + esc_attr__( 'Disable over', 'off-canvas-sidebars' ), + array( $this, 'number_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'disable_over', + 'description' => __( 'Disable off-canvas sidebars over specified screen width. Leave blank to disable.', 'off-canvas-sidebars' ), + 'input_after' => 'px', + ) + ); + add_settings_field( + 'hide_control_classes', + esc_attr__( 'Auto-hide control classes', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'hide_control_classes', + 'label' => __( 'Hide off-canvas sidebar control classes over width specified in "Disable over". Default: false.', 'off-canvas-sidebars' ), + ) + ); + add_settings_field( + 'scroll_lock', + esc_attr__( 'Scroll lock', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'scroll_lock', + 'label' => __( 'Prevent site content scrolling whilst a off-canvas sidebar is open. Default: false.', 'off-canvas-sidebars' ), + ) + ); + + add_settings_field( + 'sidebar_delete', + esc_attr__( 'Delete sidebar', 'off-canvas-sidebars' ), + array( $this, 'checkbox_option' ), + $this->sidebars_tab, + 'section_sidebar_' . $sidebar_id, + array( + 'sidebar' => $sidebar_id, + 'name' => 'delete', + 'value' => 0, + ) + ); + + } + + /** + * Parses post values, checks all values with the current existing data. + * @since 0.4 + * @param array $input + * @return array $output + */ + protected function parse_input( $input ) { + // First set current values. + $current = $this->settings; + + // Add new sidebar. + if ( ! empty( $input['sidebars']['ocs_add_new'] ) ) { + $new_sidebar_id = $this->validate_id( $input['sidebars']['ocs_add_new'] ); + if ( empty( $input['sidebars'][ $new_sidebar_id ] ) && empty( $current['sidebars'][ $new_sidebar_id ] ) ) { + $input['sidebars'][ $new_sidebar_id ] = array_merge( + off_canvas_sidebars()->get_default_sidebar_settings(), + array( + 'enable' => 1, + 'label' => strip_tags( stripslashes( $input['sidebars']['ocs_add_new'] ) ), + ) + ); + } else { + add_settings_error( + $new_sidebar_id . '_duplicate_id', + esc_attr( 'ocs_duplicate_id' ), + // Translators: %s stands for a sidebar ID. + sprintf( __( 'The ID %s already exists! Sidebar not added.', 'off-canvas-sidebars' ), '' . $new_sidebar_id . '' ) + ); + } + } + unset( $input['sidebars']['ocs_add_new'] ); + + if ( $this->post_tab === $this->settings_tab ) { + $input['enable_frontend'] = $this->validate_numeric_boolean( $input, 'enable_frontend' ); + $input['site_close'] = $this->validate_numeric_boolean( $input, 'site_close' ); + $input['hide_control_classes'] = $this->validate_numeric_boolean( $input, 'hide_control_classes' ); + $input['scroll_lock'] = $this->validate_numeric_boolean( $input, 'scroll_lock' ); + $input['use_fastclick'] = $this->validate_numeric_boolean( $input, 'use_fastclick' ); + $input['wp_editor_shortcode_rendering'] = $this->validate_numeric_boolean( $input, 'wp_editor_shortcode_rendering' ); + } + + // Handle existing sidebars. + $input = $this->parse_sidebars_input( $input, $current ); + + // Overwrite non existing values with current values. + foreach ( $current as $key => $value ) { + if ( ! isset( $input[ $key ] ) ) { + $input[ $key ] = $value; + } + } + + return $input; + } + + /** + * Parses sidebar post values, checks all values with the current existing data. + * @since 0.4 + * @param array $input + * @param array $current + * @return array + */ + private function parse_sidebars_input( $input, $current ) { + if ( empty( $current['sidebars'] ) || ! isset( $input['sidebars'] ) ) { + return $input; + } + + unset( $input['sidebars']['ocs_update'] ); + + $current = (array) $current['sidebars']; + $sidebars = (array) $input['sidebars']; + + foreach ( $current as $sidebar_id => $sidebar_data ) { + + if ( ! isset( $sidebars[ $sidebar_id ] ) ) { + $sidebars[ $sidebar_id ] = $current[ $sidebar_id ]; + // Sidebars are set but this sidebar isn't checked as active. + $sidebars[ $sidebar_id ]['enable'] = 0; + continue; + } + + // Global settings page. + if ( count( $sidebars[ $sidebar_id ] ) < 2 ) { + $current[ $sidebar_id ]['enable'] = $this->validate_checkbox( $sidebars[ $sidebar_id ]['enable'] ); + $sidebars[ $sidebar_id ] = $current[ $sidebar_id ]; + continue; + } + + // Default label is sidebar ID. + if ( empty( $sidebars[ $sidebar_id ]['label'] ) ) { + $sidebars[ $sidebar_id ]['label'] = $sidebar_id; + } + + // Change sidebar ID. + if ( ! empty( $sidebars[ $sidebar_id ]['id'] ) && $sidebar_id !== $sidebars[ $sidebar_id ]['id'] ) { + + $new_sidebar_id = $this->validate_id( $sidebars[ $sidebar_id ]['id'] ); + + if ( $sidebar_id !== $new_sidebar_id ) { + + if ( empty( $sidebars[ $new_sidebar_id ] ) ) { + + $sidebars[ $new_sidebar_id ] = $sidebars[ $sidebar_id ]; + $sidebars[ $new_sidebar_id ]['id'] = $new_sidebar_id; + + unset( $sidebars[ $sidebar_id ] ); + + // Migrate existing widgets to the new sidebar. + $this->migrate_sidebars_widgets( $sidebar_id, $new_sidebar_id ); + + } else { + add_settings_error( + $sidebar_id . '_duplicate_id', + esc_attr( 'ocs_duplicate_id' ), + // Translators: %s stands for a sidebar ID. + sprintf( __( 'The ID %s already exists! The ID is not changed.', 'off-canvas-sidebars' ), '' . $new_sidebar_id . '' ) + ); + } + } + } + } // End foreach(). + + $input['sidebars'] = $sidebars; + return $input; + } + + /** + * Validates post values. + * @since 0.1 + * @param array $input + * @return array $output + */ + public function validate_input( $input ) { + // Overwrite the old settings + $output = $this->parse_input( $input ); + + if ( $this->post_tab === $this->settings_tab ) { + // Make sure unchecked checkboxes are 0 on save. + $output['enable_frontend'] = $this->validate_checkbox( $output['enable_frontend'] ); + $output['site_close'] = $this->validate_checkbox( $output['site_close'] ); + $output['hide_control_classes'] = $this->validate_checkbox( $output['hide_control_classes'] ); + $output['scroll_lock'] = $this->validate_checkbox( $output['scroll_lock'] ); + $output['use_fastclick'] = $this->validate_checkbox( $output['use_fastclick'] ); + $output['wp_editor_shortcode_rendering'] = $this->validate_checkbox( $output['wp_editor_shortcode_rendering'] ); + + // Numeric values, not integers! + $output['disable_over'] = $this->validate_numeric( $output['disable_over'] ); + + // Remove whitespaces. + $output['website_before_hook'] = $this->remove_whitespace( $output['website_before_hook'] ); + $output['website_after_hook'] = $this->remove_whitespace( $output['website_after_hook'] ); + + // Attribute validation. + $output['css_prefix'] = $this->validate_id( $output['css_prefix'] ); + + // Validate radio options. + $output['compatibility_position_fixed'] = $this->validate_radio( $output['compatibility_position_fixed'], array( 'none', 'custom-js', 'legacy-css' ), 'none' ); + + // Set default values if no value is set. + if ( empty( $output['css_prefix'] ) ) { + $output['css_prefix'] = 'ocs'; + } + } + + foreach ( $output['sidebars'] as $sidebar_id => $sidebar_data ) { + + // Delete sidebar. + if ( ! empty( $input['sidebars'][ $sidebar_id ]['delete'] ) ) { + unset( $input['sidebars'][ $sidebar_id ] ); + unset( $output['sidebars'][ $sidebar_id ] ); + } else { + + $sidebar = $output['sidebars'][ $sidebar_id ]; + + // Make sure unchecked checkboxes are 0 on save. + $sidebar['enable'] = $this->validate_checkbox( $sidebar['enable'] ); + $sidebar['overwrite_global_settings'] = $this->validate_checkbox( $sidebar['overwrite_global_settings'] ); + $sidebar['site_close'] = $this->validate_checkbox( $sidebar['site_close'] ); + $sidebar['hide_control_classes'] = $this->validate_checkbox( $sidebar['hide_control_classes'] ); + $sidebar['scroll_lock'] = $this->validate_checkbox( $sidebar['scroll_lock'] ); + + // Numeric values, not integers! + $sidebar['padding'] = $this->validate_numeric( $sidebar['padding'] ); + $sidebar['disable_over'] = $this->validate_numeric( $sidebar['disable_over'] ); + $sidebar['animation_speed'] = $this->validate_numeric( $sidebar['animation_speed'] ); + + // Validate radio options. + $sidebar['content'] = $this->validate_radio( $sidebar['content'], array( 'sidebar', 'menu', 'action' ), 'sidebar' ); + + $output['sidebars'][ $sidebar_id ] = $sidebar; + + $new_sidebar_id = $this->validate_id( $sidebar_id ); + if ( $sidebar_id !== $new_sidebar_id ) { + $output['sidebars'][ $new_sidebar_id ] = $output['sidebars'][ $sidebar_id ]; + $output['sidebars'][ $new_sidebar_id ]['id'] = $new_sidebar_id; + + unset( $output['sidebars'][ $sidebar_id ] ); + + $this->migrate_sidebars_widgets( $sidebar_id, $new_sidebar_id ); + } + } + } // End foreach(). + + // Validate global settings with defaults. + $output = off_canvas_sidebars()->validate_settings( $output, off_canvas_sidebars()->get_default_settings() ); + // Validate sidebar settings with defaults. + foreach ( $output['sidebars'] as $sidebar_id => $sidebar_settings ) { + $output['sidebars'][ $sidebar_id ] = off_canvas_sidebars()->validate_settings( $sidebar_settings, off_canvas_sidebars()->get_default_sidebar_settings() ); + } + + unset( $output['ocs_tab'] ); + + return $output; + } + + /** + * Validates checkbox boolean values, used by validate_input(). + * @since 0.4 + * @param mixed $value + * @param string $key + * @return bool + */ + public function validate_numeric_boolean( $value, $key = '' ) { + if ( $key ) { + return (int) ( ! empty( $value[ $key ] ) ); + } + return (int) ( ! empty( $value ) ); + } + + /** + * Validates checkbox values, used by validate_input(). + * @since 0.1.2 + * @param mixed $value + * @return int + */ + public function validate_checkbox( $value ) { + return ( ! empty( $value ) ) ? (int) strip_tags( $value ) : 0; + } + + /** + * Validates radio values against the possible options. + * @since 0.4 + * @param string $value + * @param array $options + * @param string $default + * @return int + */ + public function validate_radio( $value, $options, $default ) { + return ( ! empty( $value ) && in_array( $value, $options, true ) ) ? strip_tags( $value ) : $default; + } + + /** + * Validates id values, used by validate_input. + * @since 0.2 + * @since 0.3 Convert to lowercase and convert spaces to dashes before preg_replace(). + * @param string $value + * @return string + */ + public function validate_id( $value ) { + return preg_replace( '/[^a-z0-9_-]+/i', '', str_replace( ' ', '-', strtolower( $value ) ) ); + } + + /** + * Validates numeric values, used by validate_input(). + * @since 0.2.2 + * @param mixed $value + * @return string + */ + public function validate_numeric( $value ) { + return ( ! empty( $value ) && is_numeric( $value ) ) ? (string) absint( $value ) : ''; + } + + /** + * Remove whitespace. + * @since 0.3 + * @param mixed $value + * @return string + */ + public function remove_whitespace( $value ) { + return ( ! empty( $value ) ) ? str_replace( array( ' ' ), '', (string) $value ) : ''; + } + + /** + * Updates the existing widgets when a sidebar ID changes. + * + * @since 0.3 + * @param string $old_id + * @param string $new_id + */ + public function migrate_sidebars_widgets( $old_id, $new_id ) { + $old_id = 'off-canvas-' . $old_id; + $new_id = 'off-canvas-' . $new_id; + $sidebars_widgets = wp_get_sidebars_widgets(); + + if ( ! empty( $sidebars_widgets[ $old_id ] ) ) { + $sidebars_widgets[ $new_id ] = $sidebars_widgets[ $old_id ]; + unset( $sidebars_widgets[ $old_id ] ); + } + + wp_set_sidebars_widgets( $sidebars_widgets ); + } + + /** + * Plugin Options page rendering goes here, checks for active tab and replaces key with the related settings key. + * Uses the plugin_options_tabs() method to render the tabs. + * + * @since 0.1 + */ + public function plugin_options_page() { + $do_submit = ( in_array( $this->tab, array( $this->settings_tab, $this->sidebars_tab ), true ) ) ? true : false; + ?> +
+

+ plugin_options_tabs(); ?> +
+ + tab === $this->importexport_tab ) { + $form_action = 'themes.php?page=' . $this->plugin_key . '&tab=' . $this->importexport_tab; + } + ?> + +
+ + + +

+ + + + tab === $this->settings_tab ) { ?> +

+ click here for documentation.', 'off-canvas-sidebars' ), 'https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/theme-setup' ); + ?> +

+

general_labels['compatibility_notice_theme']; ?>

+ tab === $this->sidebars_tab ) { ?> +

+ + +

+ + +
+
+
+ tab ); ?> + do_settings_sections( $this->tab ); ?> + + tab === $this->shortcode_tab ) $this->shortcode_tab(); ?> + tab === $this->importexport_tab ) $this->importexport_tab(); ?> +
+
+
+ + +
+ +
+
+

+
+

+

+ Documentation or talk about them in the Support forum', 'off-canvas-sidebars' ), 'https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/', 'https://github.com/JoryHogeveen/off-canvas-sidebars/issues' ); + ?> +

+
+

+ + PayPal - The safer, easier way to pay online! + +

+
+
+
+

+
+

+

+ +

+
+ +
+
+
+
+
+ sidebars_tab ) { + $box_classes .= ' section-sidebar if-js-closed'; + } + echo '
'; + echo ''; + if ( $section['title'] ) + echo "

{$section['title']}

\n"; + + if ( $section['callback'] ) + call_user_func( $section['callback'], $section ); + + if ( ! isset( $wp_settings_fields ) || ! isset( $wp_settings_fields[ $page ] ) || ! isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) + continue; + echo '
'; + + if ( $page === $this->sidebars_tab ) { + echo ''; + } + do_settings_fields( $page, $section['id'] ); + echo '
'; + if ( $page === $this->sidebars_tab ) { + submit_button( null, 'primary', 'submit', false ); + } + echo '
'; + echo '
'; + } + } + + /** + * Renders our tabs in the plugin options page, walks through the object's tabs array and prints them one by one. + * Provides the heading for the plugin_options_page() method. + * @since 0.1 + */ + function plugin_options_tabs() { + echo '

'; + foreach ( $this->plugin_tabs as $tab_key => $tab_caption ) { + $active = $this->tab === $tab_key ? 'nav-tab-active' : ''; + echo '' . esc_html( $tab_caption ) . ''; + } + echo '

'; + } + + /** + * Shortcode tab. + * @since 0.4 + */ + private function shortcode_tab() { + ?> +
+

:

+
+ +
+ '; + + echo '

' . __( 'Required options', 'off-canvas-sidebars' ) . ':

'; + + echo '
'; + echo ''; + echo ''; + echo '
'; + + $sidebar_select = array(); + foreach ( $this->settings['sidebars'] as $sidebar_id => $sidebar_data ) { + $sidebar_select[] = array( + 'value' => $sidebar_id, + 'label' => $sidebar_data['label'], + ); + } + $this->select_option( array( + 'name' => 'id', + 'label' => __( 'Sidebar ID', 'off-canvas-sidebars' ), + 'description' => __( '(Required) The off-canvas sidebar ID', 'off-canvas-sidebars' ), + 'options' => $sidebar_select, + ) ); + + echo '
'; + + $this->text_option( array( + 'name' => 'text', + 'label' => __( 'Text', 'off-canvas-sidebars' ), + 'value' => '', + 'class' => 'widefat', + 'description' => __( 'Limited HTML allowed', 'off-canvas-sidebars' ), + 'multiline' => true, + ) ); + + echo '
'; + + echo '
'; + + echo '

' . __( 'Optional options', 'off-canvas-sidebars' ) . ':

'; + + echo '
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + echo '
'; + + $this->select_option( array( + 'name' => 'action', + 'label' => __( 'Trigger action', 'off-canvas-sidebars' ), + 'options' => array( + array( + 'label' => __( 'Toggle', 'off-canvas-sidebars' ) . ' (' . __( 'Default', 'off-canvas-sidebars' ) . ')', + 'value' => '', + ), + array( 'label' => __( 'Open', 'off-canvas-sidebars' ), 'value' => 'open' ), + array( 'label' => __( 'Close', 'off-canvas-sidebars' ), 'value' => 'close' ), + ), + //'tooltip' => __( 'The trigger action. Default: toggle', 'off-canvas-sidebars' ), + ) ); + + echo '
'; + + $elements = array( 'button', 'span', 'a', 'b', 'strong', 'i', 'em', 'img', 'div' ); + $element_values = array(); + $element_values[] = array( + 'value' => '', + 'label' => ' - ' . __( 'Select', 'off-canvas-sidebars' ) . ' - ', + ); + foreach ( $elements as $e ) { + $element_values[] = array( + 'value' => $e, + 'label' => '' . $e . '', + ); + } + $this->select_option( array( + 'name' => 'element', + 'label' => __( 'HTML element', 'off-canvas-sidebars' ), + 'options' => $element_values, + 'description' => __( 'Choose wisely', 'off-canvas-sidebars' ) . '. ' . __( 'Default', 'off-canvas-sidebars' ) . ': button', + ) ); + + echo '
'; + + $this->text_option( array( + 'name' => 'class', + 'label' => __( 'Extra classes', 'off-canvas-sidebars' ), + 'value' => '', + 'class' => 'widefat', + 'description' => __( 'Separate multiple classes with a space', 'off-canvas-sidebars' ), + ) ); + + echo '
'; + + $this->text_option( array( + 'name' => 'attr', + 'label' => __( 'Custom attributes', 'off-canvas-sidebars' ), + 'value' => '', + 'class' => 'widefat', + 'description' => __( 'key : value ; key : value', 'off-canvas-sidebars' ), + 'multiline' => true, + ) ); + + echo '
'; + + $this->checkbox_option( array( + 'name' => 'nested', + 'label' => __( 'Nested shortcode', 'off-canvas-sidebars' ) . '?', + 'value' => '', + 'description' => __( '[ocs_trigger text="Your text"] or [ocs_trigger]Your text[/ocs_trigger]', 'off-canvas-sidebars' ), + ) ); + + echo '
'; + ?> +
+

:

+
+
+
+

HTML:

+
+ +
+ +

+ +

+ + + +

+ +

+ + plugin_key . '-submit', false ); ?> + +

+ plugin_tabs[ $this->importexport_tab ] = esc_attr__( 'Import/Export', 'off-canvas-sidebars' ); + + /** + * Check if it is the correct page. + * Capability filter documented in $this->load_plugin_data(). + */ + if ( ! current_user_can( $this->capability ) || + ! isset( $get['page'] ) || $this->plugin_key !== $get['page'] || + $this->tab !== $this->importexport_tab ) { + return; + } + + if ( isset( $get['ocs_import_result'] ) ) { + + $result_class = ''; + $ocs_import_result = ''; + + switch ( $get['ocs_import_result'] ) { + case 1: + $result_class = 'updated'; + $ocs_import_result = esc_attr__( 'Settings Imported', 'off-canvas-sidebars' ); + break; + case 2: + $result_class = 'error'; + $ocs_import_result = esc_attr__( 'Invalid Settings File', 'off-canvas-sidebars' ); + break; + case 3: + $result_class = 'error'; + $ocs_import_result = esc_attr__( 'No Settings File Selected', 'off-canvas-sidebars' ); + break; + } + + if ( ! empty( $ocs_import_result ) ) { + echo '

' . esc_html( $ocs_import_result ) . '

'; + } + + return; + } + + // Export settings. + if ( ! empty( $get['action'] ) && 'export' === $get['action'] ) { + header( "Content-Disposition: attachment; filename=" . $this->plugin_key . ".txt" ); + header( 'Content-Type: text/plain; charset=utf-8' ); + $general = $this->settings; + + echo "[START=OCS SETTINGS]\n"; + foreach ( $general as $id => $text ) + echo "$id\t" . wp_json_encode( $text ) . "\n"; + echo "[STOP=OCS SETTINGS]"; + die(); + } + + // Import settings. + if ( ! empty( $post[ $this->plugin_key . '-import' ] ) && ! empty( $_FILES[ $this->plugin_key . '-import-file' ] ) ) { + + if ( $_FILES[ $this->plugin_key . '-import-file' ]['tmp_name'] ) { + + // @codingStandardsIgnoreLine + $import = explode( "\n", file_get_contents( $_FILES[ $this->plugin_key . '-import-file' ]['tmp_name'] ) ); + if ( "[START=OCS SETTINGS]" === array_shift( $import ) && "[STOP=OCS SETTINGS]" === array_pop( $import ) ) { + + $settings = array(); + foreach ( $import as $import_option ) { + list( $key, $value ) = explode( "\t", $import_option ); + $settings[ $key ] = json_decode( $value, true ); + } + + // Validate global settings. + $settings = off_canvas_sidebars()->validate_settings( $settings, off_canvas_sidebars()->get_default_settings() ); + + // Validate sidebar settings. + if ( ! empty( $settings['sidebars'] ) ) { + foreach ( $settings['sidebars'] as $sidebar_id => $sidebar_settings ) { + $settings['sidebars'][ $sidebar_id ] = off_canvas_sidebars()->validate_settings( $sidebar_settings, off_canvas_sidebars()->get_default_sidebar_settings() ); + } + } + + $settings = array_merge( off_canvas_sidebars()->get_settings(), $settings ); + + update_option( $this->general_key, $settings ); + $ocs_import_result = 1; + } else { + $ocs_import_result = 2; + } + } else { + $ocs_import_result = 3; + } + + wp_redirect( admin_url( '/themes.php?page=' . $this->plugin_key . '&tab=' . $this->importexport_tab . '&ocs_import_result=' . esc_attr( $ocs_import_result ) ) ); + die(); + } // End if(). + + } + + /** + * Main Off-Canvas Sidebars Settings Instance. + * + * Ensures only one instance of this class is loaded or can be loaded. + * + * @since 0.3 + * @static + * @return OCS_Off_Canvas_Sidebars_Settings + */ + public static function get_instance() { + if ( is_null( self::$_instance ) ) { + self::$_instance = new self(); + } + return self::$_instance; + } + +} // End class(). diff --git a/includes/index.php b/includes/index.php index 12c197f..e3e99d5 100644 --- a/includes/index.php +++ b/includes/index.php @@ -1,2 +1,2 @@ - * @package off-canvas-sidebars - * @version 0.3 - */ - -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); - -/** - * Echos one, multiple or all OCS sidebars - * - * @since 0.3 - * @param string|array|bool $sidebars (Optional) The ID of this sidebar as configured in: Appearances > Off-Canvas Sidebars > Sidebars - */ -function the_ocs_off_canvas_sidebar( $sidebars = false ) { - if ( $instance = Off_Canvas_Sidebars_Frontend() ) { - if ( false === $sidebars ) { - $instance->do_sidebars(); - } else { - if ( is_array( $sidebars ) ) { - foreach( $sidebars as $sidebar ) { - $instance->do_sidebar( (string) $sidebar ); - } - } else { - $instance->do_sidebar( (string) $sidebars ); - } - } - } -} - -/** - * Main instance of Off-Canvas Sidebars Frontend. - * - * Returns the main instance of OCS_Off_Canvas_Sidebars_Frontend to prevent the need to use globals. - * - * @since 0.3 - * @return OCS_Off_Canvas_Sidebars_Frontend|false - */ -function Off_Canvas_Sidebars_Frontend() { - if ( class_exists( 'OCS_Off_Canvas_Sidebars_Frontend' ) ) { - return OCS_Off_Canvas_Sidebars_Frontend::get_instance(); - } - return false; -} diff --git a/includes/off-canvas-sidebars-menu-meta-box.class.php b/includes/off-canvas-sidebars-menu-meta-box.class.php deleted file mode 100644 index e6e39d0..0000000 --- a/includes/off-canvas-sidebars-menu-meta-box.class.php +++ /dev/null @@ -1,273 +0,0 @@ - - * @package off-canvas-sidebars - * @version 0.3 - * - * Credits to the Polylang plugin - */ - -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); - -final class OCS_Off_Canvas_Sidebars_Menu_Meta_box -{ - /** - * The single instance of the class. - * - * @var OCS_Off_Canvas_Sidebars_Menu_Meta_box - * @since 0.3 - */ - protected static $_instance = null; - - private $general_key = ''; - private $plugin_key = ''; - //private $plugin_tabs = array(); - private $general_settings = array(); - private $general_labels = array(); - private $link_classes = array( - '-button', - '-toggle', - // -toggle- - ); - - /** - * @since 0.3 private constructor - * @access private - */ - private function __construct() { - //add_action( 'admin_init', array( $this, 'load_settings' ) ); - add_action( 'init', array( $this, 'load_plugin_data' ) ); - add_action( 'admin_init', array( $this, 'add_meta_box' ), 11 ); - add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); - add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 2 ); - add_filter( 'wp_get_nav_menu_items', array( $this, 'wp_get_nav_menu_items' ), 20 ); // after the customizer menus - } - - /** - * Get plugin defaults - */ - function load_plugin_data() { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $this->general_settings = $off_canvas_sidebars->get_settings(); - $this->general_labels = $off_canvas_sidebars->get_general_labels(); - $this->general_key = $off_canvas_sidebars->get_general_key(); - $this->plugin_key = $off_canvas_sidebars->get_plugin_key(); - - foreach ( $this->link_classes as $key => $class ) { - $this->link_classes[ $key ] = $this->general_settings['css_prefix'] . $class; - } - } - - function add_meta_box() { - add_meta_box( $this->plugin_key.'-meta-box', __('Off-Canvas Control', 'off-canvas-sidebars'), array( $this, 'meta_box' ), 'nav-menus', 'side', 'low' ); - } - - function meta_box() { - global $_nav_menu_placeholder;//, $nav_menu_selected_id; - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1; - ?> -
-
-
    - general_settings['sidebars'] as $sidebar => $sidebar_data ) { - if ( 1 == $sidebar_data['enable'] ) { - ?> -
  • - - - - - -
  • - - is_sidebar_enabled() ) { ?> -
  • general_labels['no_sidebars_available']; ?>
  • - -
-
- is_sidebar_enabled() ) { ?> -

- - - - - - - -

- -
- base ) - return; - - $suffix = ''; //defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; - $version = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? time() : OCS_PLUGIN_VERSION; - wp_enqueue_script( 'off_canvas_control_nav_menu', OCS_PLUGIN_URL . '/js/nav-menu' . $suffix . '.js', array('jquery'), $version ); - - $data['strings'] = array( - 'show_icon' => __( 'Show icon', 'off-canvas-sidebars' ), - 'icon' => __( 'Icon classes', 'off-canvas-sidebars' ), - 'menu_item_type' => __( 'Off-Canvas Control', 'off-canvas-sidebars' ), - 'no_sidebars_available' => $this->general_labels['no_sidebars_available'], - ); - $data['controls'] = array(); - foreach ( $this->general_settings['sidebars'] as $sidebar => $sidebar_data ) { - if ( $sidebar_data['enable'] == 1 ) { - $data['controls'][ $sidebar ] = $sidebar_data['label']; - } - } - - // get all language switcher menu items - $items = get_posts( array( - 'numberposts' => -1, - 'nopaging' => true, - 'post_type' => 'nav_menu_item', - 'fields' => 'ids', - 'meta_key' => '_off_canvas_control_menu_item' - ) ); - - // the options values for the language switcher - $data['val'] = array(); - foreach ( $items as $item ) - $data['val'][ $item ] = get_post_meta( $item, '_off_canvas_control_menu_item', true ); - - // send all these data to javascript - wp_localize_script( 'off_canvas_control_nav_menu', 'off_canvas_control_data', $data ); - } - - /* - * save our menu item options - * - * @since 0.1 - * - * @param int $menu_id not used - * @param int $menu_item_db_id - */ - public function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0 ) { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - - if ( empty( $_POST['menu-item-url'][ $menu_item_db_id ] ) || $_POST['menu-item-url'][ $menu_item_db_id ] != '#off_canvas_control' ) - return; - - // security check - // as 'wp_update_nav_menu_item' can be called from outside WP admin - if ( current_user_can('edit_theme_options') ) { - - check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' ); - - $available_controls = array(); - foreach ( $this->general_settings['sidebars'] as $sidebar => $sidebar_data ) { - $available_controls[ $sidebar ] = $sidebar_data['label']; - } - - // Autoselect control when adding a new item - $default_control = ''; - if ( in_array( $_POST['menu-item-title'][ $menu_item_db_id ], $available_controls ) ) { - $default_control = $off_canvas_sidebars->get_sidebar_key_by_label( $_POST['menu-item-title'][ $menu_item_db_id ] ); - } - $options = array( 'off-canvas-control' => $default_control ); // default values - - // our jQuery form has not been displayed - if ( empty( $_POST['menu-item-off-canvas-control-detect'][ $menu_item_db_id] ) ) { - - if ( ! get_post_meta( $menu_item_db_id, '_off_canvas_control_menu_item', true ) ) // our options were never saved - update_post_meta( $menu_item_db_id, '_off_canvas_control_menu_item', $options ); - - } else { - - $options['off-canvas-control'] = ''; - - // Of only one is available, allways select it - if ( ! empty($_POST['menu-item-off-canvas-control'][ $menu_item_db_id ]) && array_key_exists( $_POST['menu-item-off-canvas-control'][ $menu_item_db_id ], $available_controls ) ) { - $options['off-canvas-control'] = strip_tags( stripslashes( $_POST['menu-item-off-canvas-control'][ $menu_item_db_id ] ) ); - } - - // Of only one sidebar is available, allways select its control - /*if (count($available_controls) == 1) { - $options['off-canvas-control'] = $off_canvas_sidebars->get_sidebar_key_by_label( $available_controls[0] ); - }*/ - update_post_meta( $menu_item_db_id, '_off_canvas_control_menu_item', $options ); // allow us to easily identify our nav menu item - } - } - } - - /* - * splits the one item of backend in several items on frontend - * take care to menu_order as it is used later in wp_nav_menu - * - * @since 0.1 - * - * @param array $items menu items - * @return array modified items - */ - public function wp_get_nav_menu_items($items) { - - if ( function_exists( 'doing_action' ) && doing_action('customize_register') || is_admin() ) { - // needed since WP 4.3, doing_action available since WP 3.9 - return $items; - } - - foreach ( $items as $key => $item ) { - if ( $options = get_post_meta( $item->ID, '_off_canvas_control_menu_item', true ) ) { - $item->url = ''; - if ( isset( $this->general_settings['sidebars'][ $options['off-canvas-control'] ] ) && 1 == $this->general_settings['sidebars'][ $options['off-canvas-control'] ]['enable'] ) { - //$item->title = $options['show_flags'] && $options['show_names'] ? $lang['flag'].' '.esc_html($lang['name']) : ($options['show_flags'] ? $lang['flag'] : esc_html($lang['name'])); - - $link_classes = $this->link_classes; - if ( ! is_array( $link_classes ) ){ - $link_classes = explode(' ', $link_classes); - } - - if ( ! empty( $options['off-canvas-control'] ) ) { - $link_classes[] = $this->general_settings['css_prefix'] . '-toggle-' . $options['off-canvas-control']; - } - - if ( ! is_array( $item->classes ) ){ - $item->classes = explode(' ', $item->classes); - } - - $item->classes = array_merge( $item->classes, $link_classes ); - } - } - } - - return $items; - } - - /** - * Main Off-Canvas Sidebars Menu Meta Box Instance. - * - * Ensures only one instance of this class is loaded or can be loaded. - * - * @since 0.3 - * @static - * @return OCS_Off_Canvas_Sidebars_Menu_Meta_box - */ - public static function get_instance() { - if ( is_null( self::$_instance ) ) { - self::$_instance = new self(); - } - return self::$_instance; - } - -} // end class \ No newline at end of file diff --git a/includes/off-canvas-sidebars-settings.class.php b/includes/off-canvas-sidebars-settings.class.php deleted file mode 100644 index 0f28e25..0000000 --- a/includes/off-canvas-sidebars-settings.class.php +++ /dev/null @@ -1,1280 +0,0 @@ - - * @package off-canvas-sidebars - * @version 0.3.1 - */ - -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); - -final class OCS_Off_Canvas_Sidebars_Settings -{ - /** - * The single instance of the class. - * - * @var OCS_Off_Canvas_Sidebars_Settings - * @since 0.3 - */ - protected static $_instance = null; - - private $general_key = ''; - private $settings_tab = 'ocs-settings'; - private $sidebars_tab = 'ocs-sidebars'; - private $importexport_tab = 'ocs-importexport'; - private $plugin_key = ''; - private $plugin_tabs = array(); - private $general_settings = array(); - private $general_labels = array(); - - /** - * @since 0.1 - * @since 0.3 private constructor - * @access private - */ - private function __construct() { - $this->plugin_key = Off_Canvas_Sidebars()->get_plugin_key(); - add_action( 'admin_init', array( $this, 'load_plugin_data' ) ); - add_action( 'admin_init', array( $this, 'register_settings' ) ); - add_action( 'admin_init', array( $this, 'register_importexport_settings' ) ); - add_action( 'admin_menu', array( $this, 'add_admin_menus' ), 15 ); - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles_scripts' ) ); - } - - /** - * Get plugin defaults - * @since 0.1 - */ - function load_plugin_data() { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $this->general_settings = $off_canvas_sidebars->get_settings(); - $this->general_labels = $off_canvas_sidebars->get_general_labels(); - $this->general_key = $off_canvas_sidebars->get_general_key(); - } - - /** - * Enqueue our styles and scripts only when it's our page - * @since 0.1 - * @param $hook - */ - function enqueue_styles_scripts( $hook ) { - if ( $hook != 'appearance_page_' . $this->plugin_key ) { - return; - } - - // Add the color picker css and script file - wp_enqueue_style( 'wp-color-picker' ); - wp_enqueue_script( 'wp-color-picker' ); - wp_enqueue_script( 'postbox' ); - - // Add our own scripts - wp_enqueue_style( 'off-canvas-sidebars-admin', OCS_PLUGIN_URL . '/css/off-canvas-sidebars-admin.css', array(), OCS_PLUGIN_VERSION ); - wp_enqueue_script( 'off-canvas-sidebars-settings', OCS_PLUGIN_URL . '/js/off-canvas-sidebars-settings.js', array( 'jquery' ), OCS_PLUGIN_VERSION, true ); - wp_localize_script( 'off-canvas-sidebars-settings', 'OCS_OFF_CANVAS_SIDEBARS_SETTINGS', array( - 'general_key' => $this->general_key, - 'plugin_key' => $this->plugin_key, - '__required_fields_not_set' => __( 'Some required fields are not set!', 'off-canvas-sidebars' ), - ) ); - - } - - /** - * Create admin page under the appearance menu - * @since 0.1 - */ - function add_admin_menus() { - add_theme_page( - esc_attr__( 'Off-Canvas Sidebars', 'off-canvas-sidebars' ), - esc_attr__( 'Off-Canvas Sidebars', 'off-canvas-sidebars' ), - apply_filters( 'ocs_settings_capability', 'edit_theme_options' ), - $this->plugin_key, - array( $this, 'plugin_options_page' ) - ); - } - - /** - * Register our settings - * @since 0.1 - */ - function register_settings() { - $this->plugin_tabs[ $this->settings_tab ] = esc_attr__( 'Settings', 'off-canvas-sidebars' ); - $this->plugin_tabs[ $this->sidebars_tab ] = esc_attr__( 'Sidebars', 'off-canvas-sidebars' ); - - register_setting( $this->settings_tab, $this->general_key, array( $this, 'validate_input' ) ); - register_setting( $this->sidebars_tab, $this->general_key, array( $this, 'validate_input' ) ); - - add_settings_section( - 'section_general', - esc_attr__( 'Global Settings', 'off-canvas-sidebars' ), - array( $this, 'register_general_settings' ), - $this->settings_tab - ); - - // Register sidebar settings - foreach ( $this->general_settings['sidebars'] as $sidebar => $sidebar_data ) { - add_settings_section( - 'section_sidebar_'.$sidebar, - __( 'Off-Canvas Sidebar', 'off-canvas-sidebars' ) . ' - ' . $this->general_settings['sidebars'][ $sidebar ]['label'] . '', - array( $this, 'register_general_settings' ), - $this->sidebars_tab - ); - $this->register_sidebar_settings( $sidebar ); - } - - do_action( 'off_canvas_sidebar_settings' ); - } - - function register_general_settings() { - add_settings_field( - 'enable_frontend', - esc_attr__( 'Enable front-end', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'enable_frontend', - 'label' => __( 'Let this plugin add the necessary elements on the front-end.', 'off-canvas-sidebars' ), - 'description' => sprintf( __( 'Read this to setup your theme for support! (Themes based on the Genesis Framework are supported by default)', 'off-canvas-sidebars' ), 'https://wordpress.org/plugins/off-canvas-sidebars/installation/' ) - ) - ); - /*add_settings_field( - 'frontend_type', - esc_attr__( 'Front-end type', 'off-canvas-sidebars' ), - array( $this, 'frontend_type_option' ), - $this->settings_tab, - 'section_general' - );*/ - add_settings_field( - 'css_prefix', - esc_attr__( 'CSS Prefix', 'off-canvas-sidebars' ), - array( $this, 'text_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'css_prefix', - 'label' => __( 'Default', 'off-canvas-sidebars' ) . ': ocs', - 'placeholder' => 'ocs', - ) - ); - add_settings_field( - 'enabled_sidebars', - esc_attr__( 'Enable Sidebars', 'off-canvas-sidebars' ), - array( $this, 'enabled_sidebars_option' ), - $this->settings_tab, - 'section_general' - ); - add_settings_field( - 'site_close', - esc_attr__( 'Close sidebar when clicking on the site', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'site_close', - 'label' => __( 'Enables closing of a off-canvas sidebar by clicking on the site. Default: true.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'disable_over', - esc_attr__( 'Disable over', 'off-canvas-sidebars' ), - array( $this, 'number_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'disable_over', - 'description' => __( 'Disable off-canvas sidebars over specified screen width. Leave blank to disable.', 'off-canvas-sidebars' ), - 'input_after' => 'px' - ) - ); - add_settings_field( - 'hide_control_classes', - esc_attr__( 'Auto-hide control classes', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'hide_control_classes', - 'label' => __( 'Hide off-canvas sidebar control classes over width specified in "Disable over". Default: false.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'scroll_lock', - esc_attr__( 'Scroll lock', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'scroll_lock', - 'label' => __( 'Prevent site content scrolling whilst a off-canvas sidebar is open. Default: false.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'background_color', - esc_attr__( 'Background color', 'off-canvas-sidebars' ), - array( $this, 'color_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'background_color', - 'description' => __( 'Choose a background color for the site container. Default: #ffffff.', 'off-canvas-sidebars' ) - ) - ); - // Genesis already has before and after hooks set - if ( get_template() != 'genesis' ) { - // Check if the before hook is filtered. If it is this setting is not needed - if ( '' != apply_filters( 'ocs_website_before_hook', '' ) ) { - add_settings_field( - 'website_before_hook', - esc_attr__( 'website_before hook name', 'off-canvas-sidebars' ), - array( $this, 'text_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'website_before_hook', - 'placeholder' => 'website_before' - ) - ); - } - // Check if the after hook is filtered. If it is this setting is not needed - if ( '' != apply_filters( 'ocs_website_after_hook', '' ) ) { - add_settings_field( - 'website_after_hook', - esc_attr__( 'website_after hook name', 'off-canvas-sidebars' ), - array( $this, 'text_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'website_after_hook', - 'placeholder' => 'website_after' - ) - ); - } - } - //https://github.com/ftlabs/fastclick - add_settings_field( - 'use_fastclick', - esc_attr__( 'Use the FastClick library?', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'use_fastclick', - 'label' => __( 'Yes. Default: disabled', 'off-canvas-sidebars' ), - 'description' => __( 'Devices with touch capability often have a 300ms delay on click triggers. FastClick is a JavaScript library purposely built to elimate the delay where neccesary.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'compatibility_position_fixed', - esc_attr__( 'Compatibility for fixed elements', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->settings_tab, - 'section_general', - array( - 'name' => 'compatibility_position_fixed', - 'label' => '('.__( 'Experimental', 'off-canvas-sidebars' ).')' - ) - ); - } - - function register_sidebar_settings( $sidebar_id ) { - - add_settings_field( - 'sidebar_enable', - esc_attr__( 'Enable', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'enable' - ) - ); - add_settings_field( - 'sidebar_id', - esc_attr__( 'ID', 'off-canvas-sidebars' ) . ' *', - array( $this, 'text_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'id', - 'value' => $sidebar_id, - 'required' => true, - 'description' => __( 'IMPORTANT: Must be unique!', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'sidebar_label', - esc_attr__( 'Name', 'off-canvas-sidebars' ), - array( $this, 'text_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'label' - ) - ); - add_settings_field( - 'sidebar_content', - esc_attr__( 'Content', 'off-canvas-sidebars' ), - array( $this, 'radio_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'content', - 'default' => 'sidebar', - 'options' => array( - 'sidebar' => array( - 'name' => 'sidebar', - 'label' => __( 'Sidebar', 'off-canvas-sidebars' ) . '   (' . __( 'Default', 'off-canvas-sidebars' ) . ')', - 'value' => 'sidebar' - ), - 'menu' => array( - 'name' => 'menu', - 'label' => __( 'Menu', 'off-canvas-sidebars' ), - 'value' => 'menu' - ), - 'action' => array( - 'name' => 'action', - 'label' => __( 'Custom', 'off-canvas-sidebars' ) . '   (' . __( 'Action hook', 'off-canvas-sidebars' ) . ': ocs_custom_content_sidebar_ )', - 'value' => 'action' - ) - ), - 'description' => __( 'Keep in mind that WordPress has menu and text widgets by default, the "sidebar" object is your best option in most cases.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'sidebar_location', - esc_attr__( 'Location', 'off-canvas-sidebars' ) . ' *', - array( $this, 'sidebar_location' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'required' => true - ) - ); - add_settings_field( - 'sidebar_size', - esc_attr__( 'Size', 'off-canvas-sidebars' ), - array( $this, 'sidebar_size' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'description' => __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'sidebar_style', - esc_attr__( 'Style', 'off-canvas-sidebars' ) . ' *', - array( $this, 'sidebar_style' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'required' => true - ) - ); - add_settings_field( - 'animation_speed', - esc_attr__( 'Animation speed', 'off-canvas-sidebars' ), - array( $this, 'number_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'animation_speed', - 'description' => - __( 'Set the animation speed for showing and hiding this sidebar. Default: 300ms', 'off-canvas-sidebars' ) . '
' . - __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), - 'input_after' => 'ms' - ) - ); - add_settings_field( - 'padding', - esc_attr__( 'Padding', 'off-canvas-sidebars' ), - array( $this, 'number_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'padding', - 'description' => - __( 'Add CSS padding (in pixels) to this sidebar. Default: none', 'off-canvas-sidebars' ) . '
' . - __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ), - 'input_after' => 'px' - ) - ); - add_settings_field( - 'background_color', - esc_attr__( 'Background color', 'off-canvas-sidebars' ), - array( $this, 'color_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'background_color', - 'description' => - __( 'Choose a background color for this sidebar. Default: #222222.', 'off-canvas-sidebars' ) . '
' . - __( 'You can overwrite this with CSS', 'off-canvas-sidebars' ) - ) - ); - - - add_settings_field( - 'overwrite_global_settings', - esc_attr__( 'Overwrite global settings', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'overwrite_global_settings' - ) - ); - add_settings_field( - 'site_close', - esc_attr__( 'Close sidebar when clicking on the site', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'site_close', - 'label' => __( 'Enables closing of a off-canvas sidebar by clicking on the site. Default: true.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'disable_over', - esc_attr__( 'Disable over', 'off-canvas-sidebars' ), - array( $this, 'number_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'disable_over', - 'description' => __( 'Disable off-canvas sidebars over specified screen width. Leave blank to disable.', 'off-canvas-sidebars' ), - 'input_after' => 'px' - ) - ); - add_settings_field( - 'hide_control_classes', - esc_attr__( 'Auto-hide control classes', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'hide_control_classes', - 'label' => __( 'Hide off-canvas sidebar control classes over width specified in "Disable over". Default: false.', 'off-canvas-sidebars' ) - ) - ); - add_settings_field( - 'scroll_lock', - esc_attr__( 'Scroll lock', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'scroll_lock', - 'label' => __( 'Prevent site content scrolling whilst a off-canvas sidebar is open. Default: false.', 'off-canvas-sidebars' ) - ) - ); - - add_settings_field( - 'sidebar_delete', - esc_attr__( 'Delete sidebar', 'off-canvas-sidebars' ), - array( $this, 'checkbox_option' ), - $this->sidebars_tab, - 'section_sidebar_' . $sidebar_id, - array( - 'sidebar' => $sidebar_id, - 'name' => 'delete', - 'value' => 0 - ) - ); - - } - - /* - * Specific fields - */ - function frontend_type_option( $args ) { - $prefixes = $this->get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - ?>
-
- - -

- -
general_key ).'[sidebars]'; - $prefixValue = $this->general_settings['sidebars']; - $prefixId = $this->general_key.'_sidebars'; - //$prefixClasses = array( $prefixId ); - if ( ! empty( $this->general_settings['sidebars'] ) ) { - ?>
$sidebar_data) { - //$classes = $this->get_option_classes( $prefixClasses, 'enable' ); - ?> -
- - -
- plugin_key ) . '&tab=' . esc_attr( $this->sidebars_tab ) . '">' - . __( 'Click here to add off-canvas sidebars', 'off-canvas-sidebars' ) . ''; - } - } - - function sidebar_location( $args ) { - $prefixes = $this->get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['sidebar'] ) ) { - $classes = $this->get_option_classes( $prefixClasses, 'location' ); - ?>
-
-
-
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['sidebar'] ) ) { - $classes = $this->get_option_classes( $prefixClasses, 'size' ); - ?>
-
-
-
- : -
- - -
- -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['sidebar'] ) ) { - $classes = $this->get_option_classes( $prefixClasses, 'style' ); - ?>
-
-
-
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - $placeholder = ''; - if ( isset( $args['placeholder'] ) ) { - $placeholder = ' placeholder="'.$args['placeholder'].'"'; - } - if ( isset( $args['name'] ) ) { - if ( isset( $args['value'] ) ) { - $prefixValue[ $args['name'] ] = $args['value']; - } - $classes = $this->get_option_classes( $prefixClasses, $args['name'] ); - ?>
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['name'] ) ) { - if ( isset( $args['value'] ) ) { - $prefixValue[ $args['name'] ] = $args['value']; - } - $classes = $this->get_option_classes( $prefixClasses, $args['name'] ); - ?>
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['name'] ) && isset( $args['options'] ) ) { - if ( isset( $args['value'] ) ) { - $prefixValue[ $args['name'] ] = $args['value']; - } - if ( ! empty( $args['default'] ) && empty( $prefixValue[ $args['name'] ] ) ) { - $prefixValue[ $args['name'] ] = $args['default']; - } - $classes = $this->get_option_classes( $prefixClasses, $args['name'] ); - ?>
- -
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['name'] ) ) { - $classes = $this->get_option_classes( $prefixClasses, $args['name'] ); - ?>
- - -

- -
get_option_prefixes( $args ); - $prefixName = $prefixes['prefixName']; - $prefixValue = $prefixes['prefixValue']; - $prefixId = $prefixes['prefixId']; - $prefixClasses = $prefixes['prefixClasses']; - if ( isset( $args['name'] ) ) { - $classes = $this->get_option_classes( $prefixClasses, $args['name'] . '_type' ); - ?>
- ()
-
-
-
- -
- -

- -
general_key ) . '[sidebars][' . $args['sidebar'] . ']'; - $prefixValue = $this->general_settings['sidebars'][ $args['sidebar'] ]; - $prefixId = $this->general_key . '_sidebars_' . $args['sidebar']; - $prefixClasses = array( - $this->general_key . '_sidebars_' . $args['sidebar'], - $this->general_key . '_sidebars' - ); - } else { - $prefixName = esc_attr( $this->general_key ); - $prefixValue = $this->general_settings; - $prefixId = $this->general_key; - $prefixClasses = array( - $this->general_key - ); - } - if ( ! empty( $args['required'] ) ) { - $prefixClasses[] = 'required'; - } - return array( 'prefixName' => $prefixName, 'prefixValue' => $prefixValue, 'prefixId' => $prefixId, 'prefixClasses' => $prefixClasses ); - } - - /** - * Combine classes prefixed with the field name - * @since 0.2 - * @param $classes - * @param $append - * @return string - */ - function get_option_classes( $classes, $append ) { - if ( $append ) { - foreach ( $classes as $key => $class ) { - if ( ! in_array( $class, array( 'required' ) ) ) - $classes[ $key ] = $class . '_' . $append; - } - } - return implode( ' ', $classes ); - } - - /** - * Validates post values - * - * @since 0.1 - * - * @param array $input - * @return array $output - */ - function validate_input( $input ) { - // First set current values - $output = $this->general_settings; - - // Add new sidebar - if ( ! empty( $input['sidebars']['ocs_add_new'] ) ) { - $new_sidebar_id = $this->validate_id( $input['sidebars']['ocs_add_new'] ); - if ( empty( $input['sidebars'][ $new_sidebar_id ] ) && empty( $output['sidebars'][ $new_sidebar_id ] ) ) { - $input['sidebars'][ $new_sidebar_id ] = array( - 'enable' => 1, - 'label' => strip_tags( stripslashes( $input['sidebars']['ocs_add_new'] ) ), - ); - } else { - add_settings_error( $new_sidebar_id . '_duplicate_id', esc_attr( 'ocs_duplicate_id' ), sprintf( __( 'The ID %s already exists! Sidebar not added.', 'off-canvas-sidebars' ), '' . $new_sidebar_id . '' ) ); - } - } - unset( $input['sidebars']['ocs_add_new'] ); - - if ( $_POST['ocs_tab'] == $this->settings_tab ) { - $input[ 'enable_frontend' ] = ( ! empty ( $input[ 'enable_frontend' ] ) ) ? 1 : 0; - $input[ 'site_close' ] = ( ! empty ( $input[ 'site_close' ] ) ) ? 1 : 0; - $input[ 'hide_control_classes' ] = ( ! empty ( $input[ 'hide_control_classes' ] ) ) ? 1 : 0; - $input[ 'scroll_lock' ] = ( ! empty ( $input[ 'scroll_lock' ] ) ) ? 1 : 0; - $input[ 'use_fastclick' ] = ( ! empty ( $input[ 'use_fastclick' ] ) ) ? 1 : 0; - $input[ 'compatibility_position_fixed' ] = ( ! empty ( $input[ 'compatibility_position_fixed' ] ) ) ? 1 : 0; - } - - // Handle existing sidebars - if ( isset( $input['sidebars'] ) ) { - - // Update trigger, always remove - if ( isset( $input['sidebars']['ocs_update'] ) ) { - unset( $input['sidebars']['ocs_update'] ); - } - - foreach ( $output['sidebars'] as $sidebar_id => $sidebar_data ) { - - if ( ! isset( $input['sidebars'][ $sidebar_id ] ) ) { - $input['sidebars'][ $sidebar_id ] = $output['sidebars'][ $sidebar_id ]; - // Sidebars are set but this sidebar isn't checked as active - $input['sidebars'][ $sidebar_id ]['enable'] = 0; - } - - // Global settings page - if ( count( $input['sidebars'][ $sidebar_id ] ) < 2 ) { - $output['sidebars'][ $sidebar_id ]['enable'] = $this->validate_checkbox( $input['sidebars'][ $sidebar_id ]['enable'] ); - $input['sidebars'][ $sidebar_id ] = $output['sidebars'][ $sidebar_id ]; - } - - // Default label is sidebar ID - if ( empty( $input['sidebars'][ $sidebar_id ]['label'] ) ) { - $input['sidebars'][ $sidebar_id ]['label'] = $sidebar_id; - } - - // Change sidebar ID - if ( ! empty( $input['sidebars'][ $sidebar_id ]['id'] ) && $sidebar_id != $input['sidebars'][ $sidebar_id ]['id'] ) { - - $new_sidebar_id = $this->validate_id( $input['sidebars'][ $sidebar_id ]['id'] ); - - if ( $sidebar_id != $new_sidebar_id ) { - - if ( empty( $input['sidebars'][ $new_sidebar_id ] ) ) { - - $input['sidebars'][ $new_sidebar_id ] = $input['sidebars'][ $sidebar_id ]; - $input['sidebars'][ $new_sidebar_id ]['id'] = $new_sidebar_id; - - unset( $input['sidebars'][ $sidebar_id ] ); - - $this->migrate_sidebars_widgets( $sidebar_id, $new_sidebar_id ); - } else { - add_settings_error( $sidebar_id . '_duplicate_id', esc_attr( 'ocs_duplicate_id' ), sprintf( __( 'The ID %s already exists! The ID is not changed.', 'off-canvas-sidebars' ), '' . $new_sidebar_id . '' ) ); - } - } - } - } - } - - // Overwrite non existing values with current values - foreach ( $output as $key => $value ) { - if ( ! isset( $input[ $key ] ) ) { - $input[ $key ] = $value; - } - } - - // Overwrite the old settings - $output = $input; - - if ( $_POST['ocs_tab'] == $this->settings_tab ) { - // Make sure unchecked checkboxes are 0 on save - $output['enable_frontend'] = $this->validate_checkbox( $output['enable_frontend'] ); - $output['site_close'] = $this->validate_checkbox( $output['site_close'] ); - $output['hide_control_classes'] = $this->validate_checkbox( $output['hide_control_classes'] ); - $output['scroll_lock'] = $this->validate_checkbox( $output['scroll_lock'] ); - $output['use_fastclick'] = $this->validate_checkbox( $output['use_fastclick'] ); - $output['compatibility_position_fixed'] = $this->validate_checkbox( $output['compatibility_position_fixed'] ); - - // Numeric values (not integers!) - $output['disable_over'] = $this->validate_numeric( $output['disable_over'] ); - - // Remove whitespaces - $output['website_before_hook'] = $this->remove_whitespace( $output['website_before_hook'] ); - $output['website_after_hook'] = $this->remove_whitespace( $output['website_after_hook'] ); - - // Attribute validation - $output['css_prefix'] = $this->validate_id( $output['css_prefix'] ); - - // Set default values if no value is set - if ( empty( $output['css_prefix'] ) ) { - $output['css_prefix'] = 'ocs'; - } - } - - foreach ( $output['sidebars'] as $sidebar_id => $sidebar_data ) { - - // Delete sidebar - if ( isset( $input['sidebars'][ $sidebar_id ]['delete'] ) && $input['sidebars'][ $sidebar_id ]['delete'] == '1' ) { - unset( $input['sidebars'][ $sidebar_id ] ); - unset( $output['sidebars'][ $sidebar_id ] ); - } else { - - // Make sure unchecked checkboxes are 0 on save - $output['sidebars'][ $sidebar_id ]['enable'] = $this->validate_checkbox( $output['sidebars'][ $sidebar_id ]['enable'] ); - $output['sidebars'][ $sidebar_id ]['overwrite_global_settings'] = $this->validate_checkbox( $output['sidebars'][ $sidebar_id ]['overwrite_global_settings'] ); - $output['sidebars'][ $sidebar_id ]['site_close'] = $this->validate_checkbox( $output['sidebars'][ $sidebar_id ]['site_close'] ); - $output['sidebars'][ $sidebar_id ]['hide_control_classes'] = $this->validate_checkbox( $output['sidebars'][ $sidebar_id ]['hide_control_classes'] ); - $output['sidebars'][ $sidebar_id ]['scroll_lock'] = $this->validate_checkbox( $output['sidebars'][ $sidebar_id ]['scroll_lock'] ); - - // Numeric values (not integers!) - $output['sidebars'][ $sidebar_id ]['padding'] = $this->validate_numeric( $output['sidebars'][ $sidebar_id ]['padding'] ); - $output['sidebars'][ $sidebar_id ]['disable_over'] = $this->validate_numeric( $output['sidebars'][ $sidebar_id ]['disable_over'] ); - $output['sidebars'][ $sidebar_id ]['animation_speed'] = $this->validate_numeric( $output['sidebars'][ $sidebar_id ]['animation_speed'] ); - - // Validate content value + set to default of not valid - $output['sidebars'][ $sidebar_id ]['content'] = ( ! empty( $output['sidebars'][ $sidebar_id ]['content'] ) && in_array( $output['sidebars'][ $sidebar_id ]['content'], array( 'sidebar', 'menu', 'action' ) ) ) ? $output['sidebars'][ $sidebar_id ]['content'] : 'sidebar'; - - $new_sidebar_id = $this->validate_id( $sidebar_id ); - if ( $sidebar_id != $new_sidebar_id ) { - $output['sidebars'][ $new_sidebar_id ] = $output['sidebars'][ $sidebar_id ]; - $output['sidebars'][ $new_sidebar_id ]['id'] = $new_sidebar_id; - - unset( $output['sidebars'][ $sidebar_id ] ); - - $this->migrate_sidebars_widgets( $sidebar_id, $new_sidebar_id ); - } - } - } - - // Validate global settings with defaults - $output = Off_Canvas_Sidebars()->validate_settings( $output, Off_Canvas_Sidebars()->get_default_settings() ); - // Validate sidebar settings with defaults - foreach ( $output['sidebars'] as $sidebar_id => $sidebar_settings ) { - $output['sidebars'][ $sidebar_id ] = Off_Canvas_Sidebars()->validate_settings( $sidebar_settings, Off_Canvas_Sidebars()->get_default_sidebar_settings() ); - } - - if ( isset( $output['ocs_tab'] ) ) { - unset( $output['ocs_tab'] ); - } - - return $output; - } - - /** - * Updates the existing widgets when a sidebar ID changes - * - * @since 0.3 - * - * @param string $oldId - * @param string $newId - */ - function migrate_sidebars_widgets( $oldId, $newId ) { - $oldId = 'off-canvas-' . $oldId; - $newId = 'off-canvas-' . $newId; - $sidebars_widgets = wp_get_sidebars_widgets(); - - if ( ! empty( $sidebars_widgets[ $oldId ] ) ) { - $sidebars_widgets[ $newId ] = $sidebars_widgets[ $oldId ]; - unset( $sidebars_widgets[ $oldId ] ); - } - - wp_set_sidebars_widgets( $sidebars_widgets ); - } - - /** - * Validates checkbox values, used by validate_input - * - * @since 0.1.2 - * - * @param mixed $value - * @return int $value - */ - function validate_checkbox( $value ) { - return ( ! empty( $value ) && $value == 1 ) ? (int) strip_tags( $value ) : 0; - } - - /** - * Validates id values, used by validate_input - * - * @since 0.2 - * @since 0.3 Convert to lowercase and convert spaces to dashes before preg_replace - * - * @param string $value - * @return string $value - */ - function validate_id( $value ) { - return preg_replace( '/[^a-z0-9_-]+/i', '', str_replace( ' ', '-', strtolower( $value ) ) ); - } - - /** - * Validates numeric values, used by validate_input - * - * @since 0.2.2 - * - * @param mixed $value - * @return string $value - */ - function validate_numeric( $value ) { - return ( ! empty( $value ) && is_numeric( $value ) ) ? (string) absint( $value ) : ''; - } - - /** - * Remove whitespace - * - * @since 0.3 - * - * @param mixed $value - * @return string $value - */ - function remove_whitespace( $value ) { - return ( ! empty( $value ) ) ? str_replace( array( ' ' ), '', (string) $value ) : ''; - } - - /* - * Plugin Options page rendering goes here, checks - * for active tab and replaces key with the related - * settings key. Uses the plugin_options_tabs method - * to render the tabs. - * - * @since 0.1 - */ - function plugin_options_page() { - $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : $this->settings_tab; - ?> -
-

- plugin_options_tabs(); ?> -
- -
- - - importexport_tab ) { ?> -

- - - - settings_tab ) { ?> -

click here for documentation.', 'off-canvas-sidebars' ), 'https://wordpress.org/plugins/off-canvas-sidebars/installation/' ); ?>

-

general_labels['compatibility_notice_theme']; ?>

- sidebars_tab ) { ?> -

- - -

- - -
-
-
- - do_settings_sections( $tab ); ?> -
-
-
- - importexport_tab ) $this->importexport_fields(); ?> - importexport_tab ) submit_button(); ?> - -
- -
-
-

-
-

-

- Documentation or talk about them in the Support forum', 'off-canvas-sidebars' ), 'https://wordpress.org/plugins/off-canvas-sidebars/installation/', 'https://wordpress.org/support/plugin/off-canvas-sidebars' ) ?> -

-
-

- - PayPal - The safer, easier way to pay online! - -

-
-
-
-

-
-

-

- -

-
- -
-
-
-
-
- sidebars_tab ) { - $box_classes .= ' section-sidebar if-js-closed'; - } - echo '
'; - echo ''; - if ( $section['title'] ) - echo "

{$section['title']}

\n"; - - if ( $section['callback'] ) - call_user_func( $section['callback'], $section ); - - if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[ $page ] ) || !isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) - continue; - echo '
'; - - if ( $page == $this->sidebars_tab ) { - echo ''; - } - do_settings_fields( $page, $section['id'] ); - echo '
'; - if ( $page == $this->sidebars_tab ) { - submit_button( null, 'primary', 'submit', false ); - } - echo '
'; - echo '
'; - } - } - - /* - * Renders our tabs in the plugin options page, - * walks through the object's tabs array and prints - * them one by one. Provides the heading for the - * plugin_options_page method. - * - * @since 0.1 - */ - function plugin_options_tabs() { - $current_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : $this->settings_tab; - - echo '

'; - foreach ( $this->plugin_tabs as $tab_key => $tab_caption ) { - $active = $current_tab == $tab_key ? 'nav-tab-active' : ''; - echo '' . esc_html( $tab_caption ) . ''; - } - echo '

'; - } - - function importexport_fields() { - ?> -

- -

- -

- - plugin_key . '-submit', false ); ?> - -

- plugin_tabs[ $this->importexport_tab ] = esc_attr__( 'Import/Export', 'off-canvas-sidebars' ); - - if ( isset( $_GET['gocs_message'] ) ) { - - $gocs_message_class = ''; - $gocs_message = ''; - - switch ( $_GET['gocs_message'] ) { - case 1: - $gocs_message_class = 'updated'; - $gocs_message = esc_attr__( 'Settings Imported', 'off-canvas-sidebars' ); - break; - case 2: - $gocs_message_class = 'error'; - $gocs_message = esc_attr__( 'Invalid Settings File', 'off-canvas-sidebars' ); - break; - case 3: - $gocs_message_class = 'error'; - $gocs_message = esc_attr__( 'No Settings File Selected', 'off-canvas-sidebars' ); - break; - default: - break; - } - - if ( ! empty( $gocs_message ) ) { - echo '

'.esc_html( $gocs_message ).'

'; - } - } - - // export settings - if ( isset( $_GET[ $this->plugin_key . '-export'] ) ) { - header( "Content-Disposition: attachment; filename=" . $this->plugin_key . ".txt" ); - header( 'Content-Type: text/plain; charset=utf-8' ); - $general = $this->general_settings; - - echo "[START=OCS SETTINGS]\n"; - foreach ( $general as $id => $text ) - echo "$id\t".json_encode( $text )."\n"; - echo "[STOP=OCS SETTINGS]"; - exit; - } - - // import settings - if ( isset( $_POST[ $this->plugin_key . '-import'] ) ) { - - if ( $_FILES[ $this->plugin_key . '-import-file' ]['tmp_name'] ) { - - $import = explode( "\n", file_get_contents( $_FILES[ $this->plugin_key . '-import-file' ]['tmp_name'] ) ); - if ( array_shift( $import ) == "[START=OCS SETTINGS]" && array_pop( $import ) == "[STOP=OCS SETTINGS]" ) { - - $settings = array(); - foreach ( $import as $import_option ) { - list( $key, $value ) = explode( "\t", $import_option ); - $settings[$key] = json_decode( sanitize_text_field( $value ), true ); - } - - // Validate global settings - $settings = Off_Canvas_Sidebars()->validate_settings( $settings, Off_Canvas_Sidebars()->get_default_settings() ); - - // Validate sidebar settings - if ( ! empty( $settings['sidebars'] ) ) { - foreach ( $settings['sidebars'] as $sidebar_id => $sidebar_settings ) { - $settings['sidebars'][ $sidebar_id ] = Off_Canvas_Sidebars()->validate_settings( $sidebar_settings, Off_Canvas_Sidebars()->get_default_sidebar_settings() ); - } - } - - update_option( $this->general_key, $settings ); - $gocs_message = 1; - } else { - $gocs_message = 2; - } - } else { - $gocs_message = 3; - } - - wp_redirect( admin_url( '/themes.php?page=' . $this->plugin_key . '&tab=' . $this->importexport_tab . '&gocs_message='.esc_attr( $gocs_message ) ) ); - exit; - } - } - - /** - * Main Off-Canvas Sidebars Settings Instance. - * - * Ensures only one instance of this class is loaded or can be loaded. - * - * @since 0.3 - * @static - * @return OCS_Off_Canvas_Sidebars_Settings - */ - public static function get_instance() { - if ( is_null( self::$_instance ) ) { - self::$_instance = new self(); - } - return self::$_instance; - } - -} // end class \ No newline at end of file diff --git a/index.php b/index.php index 12c197f..e3e99d5 100644 --- a/index.php +++ b/index.php @@ -1,2 +1,2 @@ * @package off-canvas-slidebars - * @version 0.3.1 + * @version 0.4 + * @global ocsOffCanvasSidebars + * @preserve */ -( function ( $ ) { +( function( $ ) { - $(window).load(function () { + var $window = $(window); + var $body = $('body'); - var prefix = 'ocs'; - if ( typeof ocsOffCanvasSidebars != 'undefined' ) { - prefix = ocsOffCanvasSidebars.css_prefix; + $window.on( 'ocs_initialized', function () { + + var prefix = ocsOffCanvasSidebars.css_prefix; + + if ( ocsOffCanvasSidebars._debug ) { + console.log('start fixed-scrolltop.js'); } var curScrollTopElements; - var ocs_site = $('#' + prefix + '-site'); + var scrollTarget = ocs_site = ocsOffCanvasSidebars.container; + if ( 'auto' !== ocs_site.css('overflow-y') ) { + scrollTarget = $window; + } - if ( ocs_site.css('transform') != 'none' ) { - curScrollTopElements = $('#' + prefix + '-site *').filter( function(){ return $(this).css('position') === 'fixed'; } ); - ocsScrollTopFixed(); - ocs_site.on('scroll resize', function() { - var newScrollTopElements = $('#' + prefix + '-site *').filter( function(){ return $(this).css('position') === 'fixed'; } ); - curScrollTopElements = curScrollTopElements.add(newScrollTopElements); - ocsScrollTopFixed(); - }); + function run() { + if ( 'none' !== ocs_site.css('transform') ) { + curScrollTopElements = ocsOffCanvasSidebars.getFixedElements(); + ocsOffCanvasSidebars.scrollTopFixed(); + scrollTarget.on( 'scroll resize', function() { + var newScrollTopElements = ocsOffCanvasSidebars.getFixedElements(); + curScrollTopElements = curScrollTopElements.add( newScrollTopElements ); + ocsOffCanvasSidebars.scrollTopFixed(); + } ); + scrollTarget.on( 'slidebar_event', ocsOffCanvasSidebars.slidebarEventFixed ); + } } - function ocsScrollTopFixed() { - if ( curScrollTopElements.length > 0 ) { - var scrollTop = ocs_site.scrollTop(); - var winHeight = $(window).height(); - var conOffset = ocs_site.offset(); - var conHeight = ocs_site.outerHeight(); + ocsOffCanvasSidebars.slidebarEventFixed = function( e, eventType, slidebar ) { + // Bottom slidebars. + if ( ( 'bottom' === slidebar.side && 'overlay' !== slidebar.style ) && ( 'opening' === eventType || 'closing' === eventType ) ) { curScrollTopElements.each( function() { - if ( $(this).css('position') == 'fixed' ) { - var top = $(this).css('top'); - var bottom = $(this).css('bottom'); - var px; - if ( top == 'auto' && bottom != 'auto' ) { - px = ( scrollTop + winHeight ) - ( conOffset.top + conHeight ); + var px = ocsOffCanvasSidebars._getTranslateAxis( this, 'y' ); + var offset = slidebar.element.height(); + if ( 'opening' === eventType ) { + px += offset; + } else if ( 'closing' === eventType ) { + px -= offset; + } + ocsOffCanvasSidebars.cssCompat( $(this), 'transform', 'translate( 0px, ' + px + 'px )' ); + } ); + } + }; + + ocsOffCanvasSidebars.scrollTopFixed = function() { + if ( curScrollTopElements.length ) { + var scrollTop = scrollTarget.scrollTop(), + winHeight = $window.height(), + gblOffset = $body.offset(), + conOffset = ocs_site.offset(), + conHeight = ocs_site.outerHeight(); + + var activeSidebar = ocsOffCanvasSidebars.slidebarsController.getActiveSlidebar(); + if ( activeSidebar ) { + var sidebar = ocsOffCanvasSidebars.slidebarsController.getSlidebar( activeSidebar ); + if ( 'top' === sidebar.side ) { //|| 'bottom' === sidebar.side + gblOffset.top += sidebar.element.height(); + }/* else if ( 'bottom' === sidebar.side ) { + gblOffset.top -= sidebar.element.height(); + }*/ + } + curScrollTopElements.each( function() { + var $this = $(this); + if ( 'fixed' === $this.css('position') ) { + var top = $this.css('top'), + bottom = $this.css('bottom'), + px; + if ( 'auto' === top && 'auto' !== bottom ) { + px = ( scrollTop + winHeight ) - ( conOffset.top + conHeight ) + gblOffset.top; } else { - px = scrollTop - conOffset.top; + px = scrollTop - conOffset.top + gblOffset.top; } - $(this).css({ - '-webkit-transform': 'translateY(' + px + 'px)', - '-moz-transform': 'translateY(' + px + 'px)', - 'transform': 'translateY(' + px + 'px)' - }); + ocsOffCanvasSidebars.cssCompat( $this, 'transform', 'translate( 0px, ' + px + 'px )' ); } else { - $(this).css({ - '-webkit-transform' : '', - '-moz-transform' : '', - 'transform' : '' - }); + ocsOffCanvasSidebars.cssCompat( $this, 'transform', '' ); } } ); } - } + }; + + run(); }); diff --git a/js/mce-plugin-shortcode.js b/js/mce-plugin-shortcode.js new file mode 100644 index 0000000..5338c7c --- /dev/null +++ b/js/mce-plugin-shortcode.js @@ -0,0 +1,712 @@ +;/** + * Off-Canvas Sidebars tinymce shortcode UI + * + * @author Jory Hogeveen + * @package off-canvas-slidebars + * @version 0.4 + * @global ocsMceSettings + * @preserve + * + * https://generatewp.com/take-shortcodes-ultimate-level/ + */ + +( function( tinymce, $ ) { + + tinymce.PluginManager.add( 'off_canvas_sidebars', function ( editor, url ) { + + var toolbar; + var toolbarImg; + var toolbarLink; + var toolbarElement; + var shortcode = 'ocs_trigger'; + var mceClasses = [ + 'mceItem', + 'ocsTrigger', + ocsMceSettings.prefix + '-trigger' + ]; + var singletons = [ 'br', 'hr', 'img', 'input' ]; + + $( document ).ready( function () { + if ( 'undefined' !== typeof ocsMceSettings ) { + $( '.ocs-shortcode-generator' ).removeClass( 'hidden' ); + } + } ); + + $( document ).on( 'click', '#wp-' + editor.id + '-wrap .wp-media-buttons button.ocs-shortcode-generator', function () { + var selection = editor.selection.getContent(), + $selection = $( selection ), + data = {}; + + if ( selection.length ) { + if ( $selection.is( 'img' ) ) { + data.text = $selection.attr( 'alt' ); + data.element = 'img'; + data.class = $selection.attr( 'class' ); + var attr = []; + if ( $selection.attr( 'src' ) ) { + attr.push( 'src:' + $selection.attr( 'src' ) ); + } + if ( $selection.attr( 'width' ) ) { + attr.push( 'width:' + $selection.attr( 'width' ) ); + } + if ( $selection.attr( 'height' ) ) { + attr.push( 'height:' + $selection.attr( 'height' ) ); + } + if ( $selection.attr( 'title' ) ) { + attr.push( 'title:' + $selection.attr( 'title' ) ); + } + data.attr = attr.join( ';' ); + } else { + // @todo support other elements + data.text = selection; + data.element = 'span'; + } + } + editor.execCommand( 'ocs_trigger_popup', '', data ); + return false; + } ); + + // Add popup. + editor.addCommand( 'ocs_trigger_popup', function ( ui, v ) { + + var fields = []; + // Used $.extent() to remove the original object reference. + var defaults = $.extend( true, {}, ocsMceSettings.fields ); + // Setup defaults. + for ( var field in defaults ) { + if ( ! defaults.hasOwnProperty( field ) ) { + continue; + } + var fieldData = defaults[ field ]; + if ( v[ field ] ) { + if ( 'checkbox' === fieldData.type ) { + fieldData.checked = v[ field ]; + } else { + fieldData.value = v[ field ]; + } + } + if ( 'text' === fieldData.name && 'img' === v.element ) { + fieldData.label = 'Alt'; + fieldData.tooltip = ''; + fieldData.multiline = false; + } + fields.push( fieldData ); + } + + // Open the popup. + var popup = editor.windowManager.open( { + title: ocsMceSettings.title, + body: fields, + // When the ok button is clicked. + onsubmit: function ( e ) { + // Start the shortcode tag. + var shortcode_str = '[' + shortcode; + + // Loop through our known fields. + for ( var field in ocsMceSettings.fields ) { + if ( ! ocsMceSettings.fields.hasOwnProperty( field ) ) { + continue; + } + if ( 'container' === ocsMceSettings.fields[ field ].type ) { + continue; + } + if ( 'undefined' !== typeof e.data[ field ] ) { + if ( -1 >= $.inArray( field, [ 'text', 'nested' ] ) ) { + if ( 'checkbox' === ocsMceSettings.fields[ field ].type && e.data[ field ] ) { + shortcode_str += ' ' + field + '="1"'; + } else if ( e.data[ field ].length ) { + shortcode_str += ' ' + field + '="' + e.data[ field ].replace( /(\r\n|\n|\r)/gm, '' ) + '"'; + } + } + } + } + + // If the test contains a double quote, force it to be nested for compatibility. + if ( e.data.text.length && -1 !== e.data.text.indexOf( '"' ) ) { + e.data.nested = true; + } + + // Add panel text. + if ( 'undefined' !== typeof e.data.nested && e.data.nested ) { + shortcode_str += ']' + e.data.text + '[/' + shortcode + ']'; + } else { + if ( e.data.text.length ) { + shortcode_str += ' text="' + e.data.text + '"'; + } + shortcode_str += ']'; + } + + // Insert shortcode to TinyMCE. + editor.insertContent( shortcode_str ); + } + } ); + } ); + + //tinymce.ui.OCSTriggerPopup = tinymce.ui.Control.extend( {} ); + + // Add toolbar edit button + editor.addButton( 'ocs_trigger_popup', { + tooltip: 'Edit Off-Canvas trigger', + icon: 'dashicon dashicons-admin-links', + label: 'Edit Off-Canvas trigger', + title: 'Off-Canvas trigger', + //cmd: 'ocs_trigger_popup' + onclick: function () { + doTriggerPopup( toolbarElement, editor ); + } + } ); + + // Add toolbar remove button. + editor.addButton( 'ocs_trigger_unlink', { + tooltip: 'Remove Off-Canvas trigger', + icon: 'dashicon dashicons-editor-unlink', + label: 'Remove Off-Canvas trigger', + //cmd: 'ocs_trigger_popup' + onclick: function () { + removeTriggerData( toolbarElement, editor ); + toolbarElement = null; + tinymce.toolbar = null; + //editor.execCommand( 'unlink' ); + } + } ); + + // Add toolbar remove button. + editor.addButton( 'ocs_trigger_remove', { + tooltip: 'Remove', + icon: 'dashicon dashicons-no', + label: 'Remove', + //cmd: 'ocs_trigger_popup' + onclick: function () { + $( toolbarElement ).remove(); + toolbarElement = null; + editor.execCommand( 'unlink' ); + } + } ); + + // Create toolbar. + editor.on( 'preinit', function () { + if ( editor.wp && editor.wp._createToolbar ) { + toolbar = editor.wp._createToolbar( [ + 'ocs_trigger_popup', + 'ocs_trigger_unlink', + 'ocs_trigger_remove' + ], true ); + + toolbarImg = editor.wp._createToolbar( [ + 'wp_img_alignleft', + 'wp_img_aligncenter', + 'wp_img_alignright', + 'wp_img_alignnone', + 'ocs_trigger_popup', + 'ocs_trigger_unlink', + 'wp_img_edit', + 'wp_img_remove' + ], true ); + + toolbarLink = editor.wp._createToolbar( [ + 'wp_link_preview', + 'ocs_trigger_popup', + 'ocs_trigger_unlink', + 'wp_link_edit', + 'wp_link_remove' + ], true ); + } + } ); + + // Show toolbar. + editor.on( 'wptoolbar', function ( e ) { + if ( -1 < e.element.className.indexOf( 'ocsTrigger' ) ) { + toolbarElement = e.element; + if ( $( e.element ).is( 'img' ) ) { + e.toolbar = toolbarImg; + } else if( $( e.element ).is( 'a' ) ) { + e.toolbar = toolbarLink; + } else { + // @todo support wpLink + e.toolbar = toolbar; + } + } + } ); + + // Disable our button if the selected text is already a OCS shortcode. + editor.on( 'NodeChange', function ( e ) { + if ( -1 < e.element.className.indexOf( 'ocsTrigger' ) ) { + $( e.target.container ).closest( '.wp-editor-wrap' ).find( 'button.ocs-shortcode-generator' ).attr( 'disabled', true ); + } else { + $( e.target.container ).closest( '.wp-editor-wrap' ).find( 'button.ocs-shortcode-generator' ).attr( 'disabled', false ); + } + } ); + + // Always enable the button again when the editor gets blurred (out of focus). + editor.on( 'Blur', function ( e ) { + $( e.target.container ).closest( '.wp-editor-wrap' ).find( 'button.ocs-shortcode-generator' ).attr( 'disabled', false ); + } ); + + editor.on( 'BeforeSetcontent', function ( e ) { + if ( ocsMceSettings.render ) { + e.content = replaceShortcodes( e.content ); + } + } ); + + editor.on( 'GetContent', function ( e ) { + e.content = restoreShortcodes( e.content ); + } ); + + editor.on( 'DblClick', function ( e ) { + if ( -1 < e.target.className.indexOf( 'ocsTrigger' ) ) { + doTriggerPopup( e.target, this ); + } + } ); + + /** + * Sets the selected element and the element data before triggering the popup + * + * @param {string} el The element HTML. + * @param {object} curEditor The current editor. + * @return {null} Nothing. + */ + function doTriggerPopup( el, curEditor ) { + curEditor.selection.select( el ); + var $el = $( el ), + attr = parseHTMLToData( el ), + data = {}; + + // Loop through our known fields. + for ( var field in ocsMceSettings.fields ) { + if ( ! ocsMceSettings.fields.hasOwnProperty( field ) ) { + continue; + } + if ( 'container' === ocsMceSettings.fields[ field ].type ) { + continue; + } + if ( 'checkbox' === ocsMceSettings.fields[ field ].type ) { + data[ field ] = ( '1' === attr[ field ] ); + } else { + data[ field ] = attr[ field ]; + } + } + + data = objectRemoveEmpty( data ); + + // overwrites. + data.nested = ( 'true' === $el.attr( 'data-ocs-nested' ) ); + data.text = parseElementText( el ); + + curEditor.execCommand( 'ocs_trigger_popup', '', data ); + } + + /** + * Find the OCS shortcode in a block of text and parse them to actual HTML. + * @param {string} content The content. + * @return {string} The new HTML. + */ + function replaceShortcodes( content ) { + + //match [ocs_trigger(attr)](con)[/ocs_trigger] + content = content.replace( /\[ocs_trigger([^\]]*)\]([^\]]*)\[\/ocs_trigger\]/g, function ( all, attr, con ) { + return parseDataToHTML( 'ocsTrigger', attr, con, true ); + } ); + + //match [ocs_trigger(attr)] + content = content.replace( /\[ocs_trigger([^\]]*)\]/g, function ( all, attr ) { + return parseDataToHTML( 'ocsTrigger', attr, '', false ); + } ); + + return content; + } + + /** + * Convert Trigger HTML into shortcodes. + * @param {string} content The content. + * @return {string} The new HTML. + */ + function restoreShortcodes( content ) { + + var html = $( '
' ).html( content ); + + $( html ).find( '.mceItem.ocsTrigger' ).each( function () { + var attr = parseHTMLToData( this ); + var text = parseElementText( this ); + var nested = window.decodeURIComponent( $( this ).attr( 'data-ocs-nested' ) ); + + if ( 'true' === nested ) { + delete attr.text; + attr = attrObjectToHTML( attr ); + $( this ).replaceWith( '[' + shortcode + ' ' + attr + ']' + text + '[/' + shortcode + ']' ); + } else { + attr.text = text; + attr = attrObjectToHTML( attr ); + $( this ).replaceWith( '[' + shortcode + ' ' + attr + ']' ); + } + } ); + + content = $( html ).html(); + return content; + } + + /** + * Convert data to HTML. + * @param {string} cls Class. + * @param {string} data Attribute data. + * @param {string} con Content. + * @param {boolean} nested Is it a nested shortcode? + * @return {string} The HTML. + */ + function parseDataToHTML( cls, data, con, nested ) { + var attrData = { + //id: getAttr( data, 'id' ), + //action: getAttr( data, 'action' ), + element: getAttr( data, 'element', false ), + class: getAttr( data, 'class', false ), + attributes: getAttr( data, 'attr', false ) + }; + + if ( ! nested ) { + con = getAttr( data, 'text', false ); + } + + if ( ! attrData.attributes.length ) { + attrData.attributes = getAttr( data, 'attributes', false ); + } + + if ( ! attrData.class.length ) { + attrData.class = getAttr( data, 'classes', false ); + } + + if ( ! attrData.element.length ) { + attrData.element = 'button'; + } + + var attributes = attrStringToObject( attrData.attributes ); + + var classes = []; + classes.push( 'mceItem', cls ); + if ( 'string' === typeof attributes.class ) { + classes = classes.concat( attributes.class.split( ' ' ) ); + delete attributes.class; + } + if ( attrData.class.length ) { + classes = classes.concat( attrData.class.split( ' ' ) ); + } + + attrData.class = arrayFilterUnique( classes, true, true ).join( ' ' ); + attributes.class = arrayFilterUnique( classes, true, false ).join( ' ' ); + attributes = objectRemoveEmpty( attributes ); + + data = attrHTMLToObject( data ); + for ( var key in attrData ) { + if ( attrData.hasOwnProperty( key ) ) { + data[ key ] = attrData[ key ]; + } + } + // Remove duplicates and empty values. + data = objectRemoveEmpty( data ); + data = attrObjectToHTML( data ); + + data = window.encodeURIComponent( data ); + + var content = window.encodeURIComponent( con ); + // Some text is required for the editor to work properly. + if ( ! content.length && 'img' !== attrData.element ) { + content = con = ' '; + } + + if ( 'img' === attrData.element ) { // && 'string' !== typeof elAttributes.alt + attributes.alt = content; + } + + attributes['data-ocs-nested'] = nested; + attributes['data-ocs-attr'] = data; + attributes['data-ocs-text'] = content; + + var elAttributes = attrObjectToHTML( attributes ); + + if ( -1 < $.inArray( attrData.element, singletons ) ) { + return '<' + attrData.element + ' ' + elAttributes + ' />'; + } else { + return '<' + attrData.element + ' ' + elAttributes + '>' + con + ''; + } + // data-mce-resize="false" data-mce-placeholder="1" + } + + /** + * Convert attribute string to attribute object. + * @param {string|object} el The element. + * @return {Object} + */ + function parseHTMLToData( el ) { + var attr = window.decodeURIComponent( $( el ).attr( 'data-ocs-attr' ) ); + + var attributes = attrHTMLToObject( attr ); + var elAttributes = attrElementToObject( el ); + + // Overwrites. + if ( 'undefined' !== typeof attributes.attributes ) { + if ( 'string' !== typeof attributes.attr ) { + attributes.attr = attributes.attributes; + } + delete attributes.attributes; + } + if ( 'undefined' !== typeof attributes.classes ) { + if ( 'string' !== typeof attributes.class ) { + attributes.class = attributes.classes; + } + delete attributes.classes; + } + + // Converting. + if ( 'string' === typeof attributes.attr ) { + attributes.attr = attrStringToObject( attributes.attr ); + } else { + attributes.attr = {}; + } + + for ( var key in elAttributes ) { + if ('class' === key && elAttributes.class.length ) { + // append + if ( 'string' === typeof attributes.class ) { + attributes.class += ' ' + elAttributes.class; + } else { + attributes.class = elAttributes.class; + } + } else if ( -1 === key.indexOf( 'data-' ) && 'string' === typeof elAttributes[ key ] ) { + // overwrite, check for alt tag for images. + if ( 'alt' === key && $( el ).is( 'img' ) ) { + delete attributes.attr[ key ]; + } else { + attributes.attr[ key ] = '' + elAttributes[ key ]; + } + } + } + + if ( 'string' === typeof attributes.class && attributes.class.trim().length ) { + // Convert classes to an array. + attributes.class = attributes.class.split( ' ' ); + // Remove MCE plugin defined classes. + attributes.class = arrayFilterUnique( attributes.class, true, true ); + // Rejoin the classes. + attributes.class = attributes.class.join( ' ' ); + } + + if ( 'object' === typeof attributes.attr ) { + attributes.attr = attrObjectToString( attributes.attr ); + } + + // Remove duplicate and empty attributes. + attributes = objectRemoveEmpty( attributes ); + + return attributes; + } + + /** + * Get the element text, also checks for nested element attributes. + * @param {string|object} el The element. + * @return {string} The text. + */ + function parseElementText( el ) { + var $el = $( el ), + text = window.decodeURIComponent( $el.attr( 'data-ocs-text' ) ); + if ( $el.html().length ) { + text = $el.html(); + } + + // Images have the alt tag for text. + if ( $el.is('img') ) { + if ( $el.attr('alt') ) { + text = $el.attr('alt'); + } else { + text = ''; + } + } + return text; + } + + /** + * Remove OCS classes & attributes. + * @param {string|object} el The element. + * @param {object} editor The editor. + */ + function removeTriggerData( el, editor ) { + var $el = $( el ); + $el.removeClass( 'mceItem' ); + $el.removeClass( 'ocsTrigger' ); + $el.removeAttr( 'data-ocs-attr' ); + $el.removeAttr( 'data-ocs-text' ); + $el.removeAttr( 'data-ocs-nested' ); + //$el.removeAttr( 'data-mce-placeholder' ); + } + + /** + * @param {string} s The string. + * @param {string} a The attribute to find. + * @param {boolean} f @todo + * @return {string|boolean} The attribute value or false. + */ + function getAttr( s, a, f ) { + var n = new RegExp( a + '=\"([^\"]+)\"', 'g' ).exec( s ); + if ( true === f && !n && -1 === s.indexOf( a + '="' ) ) { + // Attribute does not exist + return false; + } + return n ? window.decodeURIComponent( n[ 1 ] ).trim() : ''; + } + + /** + * Get attributes from a jQuery element + * If it contains multiple elements it only returns attributes from the first + * + * In: element + * Out: { key: value, key: value } + * + * @since 0.4 + * @param {string|object} el The element. + * @return {object} The attribute object. + */ + function attrElementToObject( el ) { + var $el = $( el ), + atts = {}; + if ( $el.length ) { + $.each( $el[ 0 ].attributes, function ( index, attr ) { + atts[ attr.name ] = attr.value; + } ); + } + return atts; + } + + /** + * Convert HTML formatted attribute string to object. + * In: key="value" key="value" + * Out: { key: value, key: value } + * + * @since 0.4 + * @param {string} attrString The attribute string. + * @return {object} The attribute object. + */ + function attrHTMLToObject( attrString ) { + var arr = attrString.trim().split( '" ' ), + atts = {}; + for ( var key in arr ) { + if ( arr.hasOwnProperty( key ) ) { + arr[ key ] = arr[ key ].split( '="' ); + if ( arr[ key ][ 0 ].trim().length ) { + atts[ arr[ key ][ 0 ].trim() ] = getAttr( attrString, arr[ key ][ 0 ], false ); + } + } + } + return atts; + } + + /** + * Convert OCS formatted attribute string to object. + * + * In: key:value;key:value + * Out: { key: value, key: value } + * + * @since 0.4 + * @param {string} attrString The attribute string. + * @return {object} The attribute object. + */ + function attrStringToObject( attrString ) { + var arr = attrString.split( ';' ), + atts = {}; + for ( var key in arr ) { + if ( arr.hasOwnProperty( key ) ) { + arr[ key ] = arr[ key ].split( ':' ); + if ( arr[ key ][ 0 ].trim().length ) { + var name = arr[ key ][ 0 ].trim(); + arr[ key ].splice( 0, 1 ); + atts[ name ] = arr[ key ].join( ':' ); + } + } + } + return atts; + } + + /** + * Convert object to OCS formatted attribute string. + * + * In: { key: value, key: value } + * Out: key="value" key="value" + * + * @since 0.4 + * @param {object} attrObj The attribute object. + * @return {string} The attribute string. + */ + function attrObjectToHTML( attrObj ) { + var atts = []; + for ( var name in attrObj ) { + if ( attrObj.hasOwnProperty( name ) ) { + atts.push( name + '="' + attrObj[ name ] + '"' ); + } + } + return atts.join( ' ' ); + } + + /** + * Convert object to HTML formatted attribute string. + * + * In: { key: value, key: value } + * Out: key:value;key:value + * + * @since 0.4 + * @param {object} attrObj The attribute object. + * @return {string} The attribute string. + */ + function attrObjectToString( attrObj ) { + var atts = []; + for ( var name in attrObj ) { + if ( attrObj.hasOwnProperty( name ) ) { + atts.push( name + ':' + attrObj[ name ] ); + } + } + return atts.join( ';' ); + } + + /** + * Return unique values only. + * + * @param {object} array The array to filter. + * @param {boolean} empty Remove empty keys? + * @param {boolean} ocs Check this plugin's defines classes. + * @return {object} The filtered array. + */ + function arrayFilterUnique( array, empty, ocs ) { + if ( ! array.length ) { + return []; + } + return $.grep( array, function ( el, index ) { + if ( empty && !el.length ) { + return false; + } + if ( ocs && -1 < $.inArray( el, mceClasses ) ) { + return false; + } + return index === $.inArray( el, array ); + } ); + } + + /** + * Remove empty properties from object. + * Only objects with strings as values allowed! + * + * @param {object} obj The object to filter. + * @return {object} The object without empty keys. + */ + function objectRemoveEmpty( obj ) { + for ( var name in obj ) { + if ( ! obj.hasOwnProperty( name ) ) { + continue; + } + if ( 'string' === typeof obj[ name ] ) { + obj[ name ] = obj[ name ].trim(); + } + if ( null === obj[ name ] || undefined === obj[ name ] || ! obj[ name ].length ) { + delete obj[ name ]; + } + } + return obj; + } + + } ); + +} ) ( window.tinymce, jQuery ); diff --git a/js/mce-plugin-shortcode.min.js b/js/mce-plugin-shortcode.min.js new file mode 100644 index 0000000..414287c --- /dev/null +++ b/js/mce-plugin-shortcode.min.js @@ -0,0 +1,12 @@ +;/** + * Off-Canvas Sidebars tinymce shortcode UI + * + * @author Jory Hogeveen + * @package off-canvas-slidebars + * @version 0.4 + * @global ocsMceSettings + * @preserve + * + * https://generatewp.com/take-shortcodes-ultimate-level/ + */ +(function(tinymce,$){tinymce.PluginManager.add("off_canvas_sidebars",function(editor,url){var toolbar;var toolbarImg;var toolbarLink;var toolbarElement;var shortcode="ocs_trigger";var mceClasses=["mceItem","ocsTrigger",ocsMceSettings.prefix+"-trigger"];var singletons=["br","hr","img","input"];$(document).ready(function(){if("undefined"!==typeof ocsMceSettings){$(".ocs-shortcode-generator").removeClass("hidden")}});$(document).on("click","#wp-"+editor.id+"-wrap .wp-media-buttons button.ocs-shortcode-generator",function(){var selection=editor.selection.getContent(),$selection=$(selection),data={};if(selection.length){if($selection.is("img")){data.text=$selection.attr("alt");data.element="img";data.class=$selection.attr("class");var attr=[];if($selection.attr("src")){attr.push("src:"+$selection.attr("src"))}if($selection.attr("width")){attr.push("width:"+$selection.attr("width"))}if($selection.attr("height")){attr.push("height:"+$selection.attr("height"))}if($selection.attr("title")){attr.push("title:"+$selection.attr("title"))}data.attr=attr.join(";")}else{data.text=selection;data.element="span"}}editor.execCommand("ocs_trigger_popup","",data);return false});editor.addCommand("ocs_trigger_popup",function(ui,v){var fields=[];var defaults=$.extend(true,{},ocsMceSettings.fields);for(var field in defaults){if(!defaults.hasOwnProperty(field)){continue}var fieldData=defaults[field];if(v[field]){if("checkbox"===fieldData.type){fieldData.checked=v[field]}else{fieldData.value=v[field]}}if("text"===fieldData.name&&"img"===v.element){fieldData.label="Alt";fieldData.tooltip="";fieldData.multiline=false}fields.push(fieldData)}var popup=editor.windowManager.open({title:ocsMceSettings.title,body:fields,onsubmit:function(e){var shortcode_str="["+shortcode;for(var field in ocsMceSettings.fields){if(!ocsMceSettings.fields.hasOwnProperty(field)){continue}if("container"===ocsMceSettings.fields[field].type){continue}if("undefined"!==typeof e.data[field]){if(-1>=$.inArray(field,["text","nested"])){if("checkbox"===ocsMceSettings.fields[field].type&&e.data[field]){shortcode_str+=" "+field+'="1"'}else if(e.data[field].length){shortcode_str+=" "+field+'="'+e.data[field].replace(/(\r\n|\n|\r)/gm,"")+'"'}}}}if(e.data.text.length&&-1!==e.data.text.indexOf('"')){e.data.nested=true}if("undefined"!==typeof e.data.nested&&e.data.nested){shortcode_str+="]"+e.data.text+"[/"+shortcode+"]"}else{if(e.data.text.length){shortcode_str+=' text="'+e.data.text+'"'}shortcode_str+="]"}editor.insertContent(shortcode_str)}})});editor.addButton("ocs_trigger_popup",{tooltip:"Edit Off-Canvas trigger",icon:"dashicon dashicons-admin-links",label:"Edit Off-Canvas trigger",title:"Off-Canvas trigger",onclick:function(){doTriggerPopup(toolbarElement,editor)}});editor.addButton("ocs_trigger_unlink",{tooltip:"Remove Off-Canvas trigger",icon:"dashicon dashicons-editor-unlink",label:"Remove Off-Canvas trigger",onclick:function(){removeTriggerData(toolbarElement,editor);toolbarElement=null;tinymce.toolbar=null}});editor.addButton("ocs_trigger_remove",{tooltip:"Remove",icon:"dashicon dashicons-no",label:"Remove",onclick:function(){$(toolbarElement).remove();toolbarElement=null;editor.execCommand("unlink")}});editor.on("preinit",function(){if(editor.wp&&editor.wp._createToolbar){toolbar=editor.wp._createToolbar(["ocs_trigger_popup","ocs_trigger_unlink","ocs_trigger_remove"],true);toolbarImg=editor.wp._createToolbar(["wp_img_alignleft","wp_img_aligncenter","wp_img_alignright","wp_img_alignnone","ocs_trigger_popup","ocs_trigger_unlink","wp_img_edit","wp_img_remove"],true);toolbarLink=editor.wp._createToolbar(["wp_link_preview","ocs_trigger_popup","ocs_trigger_unlink","wp_link_edit","wp_link_remove"],true)}});editor.on("wptoolbar",function(e){if(-1").html(content);$(html).find(".mceItem.ocsTrigger").each(function(){var attr=parseHTMLToData(this);var text=parseElementText(this);var nested=window.decodeURIComponent($(this).attr("data-ocs-nested"));if("true"===nested){delete attr.text;attr=attrObjectToHTML(attr);$(this).replaceWith("["+shortcode+" "+attr+"]"+text+"[/"+shortcode+"]")}else{attr.text=text;attr=attrObjectToHTML(attr);$(this).replaceWith("["+shortcode+" "+attr+"]")}});content=$(html).html();return content}function parseDataToHTML(cls,data,con,nested){var attrData={element:getAttr(data,"element",false),"class":getAttr(data,"class",false),attributes:getAttr(data,"attr",false)};if(!nested){con=getAttr(data,"text",false)}if(!attrData.attributes.length){attrData.attributes=getAttr(data,"attributes",false)}if(!attrData.class.length){attrData.class=getAttr(data,"classes",false)}if(!attrData.element.length){attrData.element="button"}var attributes=attrStringToObject(attrData.attributes);var classes=[];classes.push("mceItem",cls);if("string"===typeof attributes.class){classes=classes.concat(attributes.class.split(" "));delete attributes.class}if(attrData.class.length){classes=classes.concat(attrData.class.split(" "))}attrData.class=arrayFilterUnique(classes,true,true).join(" ");attributes.class=arrayFilterUnique(classes,true,false).join(" ");attributes=objectRemoveEmpty(attributes);data=attrHTMLToObject(data);for(var key in attrData){if(attrData.hasOwnProperty(key)){data[key]=attrData[key]}}data=objectRemoveEmpty(data);data=attrObjectToHTML(data);data=window.encodeURIComponent(data);var content=window.encodeURIComponent(con);if(!content.length&&"img"!==attrData.element){content=con=" "}if("img"===attrData.element){attributes.alt=content}attributes["data-ocs-nested"]=nested;attributes["data-ocs-attr"]=data;attributes["data-ocs-text"]=content;var elAttributes=attrObjectToHTML(attributes);if(-1<$.inArray(attrData.element,singletons)){return"<"+attrData.element+" "+elAttributes+" />"}else{return"<"+attrData.element+" "+elAttributes+">"+con+""}}function parseHTMLToData(el){var attr=window.decodeURIComponent($(el).attr("data-ocs-attr"));var attributes=attrHTMLToObject(attr);var elAttributes=attrElementToObject(el);if("undefined"!==typeof attributes.attributes){if("string"!==typeof attributes.attr){attributes.attr=attributes.attributes}delete attributes.attributes}if("undefined"!==typeof attributes.classes){if("string"!==typeof attributes.class){attributes.class=attributes.classes}delete attributes.classes}if("string"===typeof attributes.attr){attributes.attr=attrStringToObject(attributes.attr)}else{attributes.attr={}}for(var key in elAttributes){if("class"===key&&elAttributes.class.length){if("string"===typeof attributes.class){attributes.class+=" "+elAttributes.class}else{attributes.class=elAttributes.class}}else if(-1===key.indexOf("data-")&&"string"===typeof elAttributes[key]){if("alt"===key&&$(el).is("img")){delete attributes.attr[key]}else{attributes.attr[key]=""+elAttributes[key]}}}if("string"===typeof attributes.class&&attributes.class.trim().length){attributes.class=attributes.class.split(" ");attributes.class=arrayFilterUnique(attributes.class,true,true);attributes.class=attributes.class.join(" ")}if("object"===typeof attributes.attr){attributes.attr=attrObjectToString(attributes.attr)}attributes=objectRemoveEmpty(attributes);return attributes}function parseElementText(el){var $el=$(el),text=window.decodeURIComponent($el.attr("data-ocs-text"));if($el.html().length){text=$el.html()}if($el.is("img")){if($el.attr("alt")){text=$el.attr("alt")}else{text=""}}return text}function removeTriggerData(el,editor){var $el=$(el);$el.removeClass("mceItem");$el.removeClass("ocsTrigger");$el.removeAttr("data-ocs-attr");$el.removeAttr("data-ocs-text");$el.removeAttr("data-ocs-nested")}function getAttr(s,a,f){var n=new RegExp(a+'="([^"]+)"',"g").exec(s);if(true===f&&!n&&-1===s.indexOf(a+'="')){return false}return n?window.decodeURIComponent(n[1]).trim():""}function attrElementToObject(el){var $el=$(el),atts={};if($el.length){$.each($el[0].attributes,function(index,attr){atts[attr.name]=attr.value})}return atts}function attrHTMLToObject(attrString){var arr=attrString.trim().split('" '),atts={};for(var key in arr){if(arr.hasOwnProperty(key)){arr[key]=arr[key].split('="');if(arr[key][0].trim().length){atts[arr[key][0].trim()]=getAttr(attrString,arr[key][0],false)}}}return atts}function attrStringToObject(attrString){var arr=attrString.split(";"),atts={};for(var key in arr){if(arr.hasOwnProperty(key)){arr[key]=arr[key].split(":");if(arr[key][0].trim().length){var name=arr[key][0].trim();arr[key].splice(0,1);atts[name]=arr[key].join(":")}}}return atts}function attrObjectToHTML(attrObj){var atts=[];for(var name in attrObj){if(attrObj.hasOwnProperty(name)){atts.push(name+'="'+attrObj[name]+'"')}}return atts.join(" ")}function attrObjectToString(attrObj){var atts=[];for(var name in attrObj){if(attrObj.hasOwnProperty(name)){atts.push(name+":"+attrObj[name])}}return atts.join(";")}function arrayFilterUnique(array,empty,ocs){if(!array.length){return[]}return $.grep(array,function(el,index){if(empty&&!el.length){return false}if(ocs&&-1<$.inArray(el,mceClasses)){return false}return index===$.inArray(el,array)})}function objectRemoveEmpty(obj){for(var name in obj){if(!obj.hasOwnProperty(name)){continue}if("string"===typeof obj[name]){obj[name]=obj[name].trim()}if(null===obj[name]||undefined===obj[name]||!obj[name].length){delete obj[name]}}return obj}})})(window.tinymce,jQuery); \ No newline at end of file diff --git a/js/nav-menu.js b/js/nav-menu.js index 39ea113..9f0afe7 100644 --- a/js/nav-menu.js +++ b/js/nav-menu.js @@ -4,106 +4,96 @@ * Menu Meta Box scripts * @author Jory Hogeveen * @package off-canvas-slidebars - * @version 0.2 + * @version 0.4 + * @global ocsNavControl + * @preserve * * Credits to the Polylang plugin for inspiration */ -jQuery(document).ready(function($) { +if ( 'undefined' === typeof ocsNavControl ) { + var ocsNavControl = {}; +} + +jQuery( document ).ready( function( $ ) { $("input[value='#off_canvas_control'][type=text]").parent().parent().parent().parent().each( function() { - $(this).addClass('off-canvas-control'); - /* Is control selected, then show it */ - var control_type = ''; - if (off_canvas_control_data.val[$(this).find('.menu-item-data-db-id').val()]['off-canvas-control']) { - var key = off_canvas_control_data.val[$(this).find('.menu-item-data-db-id').val()]['off-canvas-control']; - control_type = ' ('+off_canvas_control_data.controls[key]+')'; + var $this = $(this), + control_type = '', + db_id = $this.find('.menu-item-data-db-id').val(); + $this.addClass('off-canvas-control'); + + /* If control selected, then show it */ + if ( ocsNavControl.val[ db_id ]['off-canvas-control']) { + var key = ocsNavControl.val[ db_id ]['off-canvas-control']; + control_type = ' (' + ocsNavControl.controls[ key ] + ')'; } - $(this).find('.menu-item-bar .item-type').html(off_canvas_control_data.strings.menu_item_type+control_type); + $this.find('.menu-item-bar .item-type').html( ocsNavControl.strings.menu_item_type + control_type ); }); - /* change menu type label on selecting a controller */ - $(document).on('change', '.field-off-canvas-control input', function(e) { + /* Change menu type label on selecting a controller */ + $(document).on( 'change', '.field-off-canvas-control input', function() { var key = $(this).val(); - var control_type = ' ('+off_canvas_control_data.controls[key]+')'; - $(this).parents('.menu-item').find('.menu-item-bar .item-type').html(off_canvas_control_data.strings.menu_item_type+control_type); - }); - - /* init/change menu item options */ - $('#update-nav-menu').bind('click load', function(e) { - if ( e.target && e.target.className && -1 != e.target.className.indexOf('item-edit')) { - $("input[value='#off_canvas_control'][type=text]").parent().parent().parent().each( function(){ - var item = $(this).attr('id').substring(19); - - var strings = off_canvas_control_data.strings; + var control_type = ' (' + ocsNavControl.controls[ key ] + ')'; + $(this).parents('.menu-item').find('.menu-item-bar .item-type').html( ocsNavControl.strings.menu_item_type + control_type ); + } ); - $(this).children('p.field-url, p.field-link-target, .field-xfn, .field-description').remove(); // remove default fields we don't need - $(this).children('p.field-css-classes').removeClass('description-thin').addClass('description-wide'); + /* Init/change menu item options */ + $('#update-nav-menu').bind( 'click load', function(e) { + if ( e.target && e.target.className && -1 < e.target.className.indexOf('item-edit')) { + $('input[value="#off_canvas_control"][type=text]').parent().parent().parent().each( function() { + var $this = $(this), + item = $this.attr('id').substring(19), + strings = ocsNavControl.strings, + controls = ocsNavControl.controls, + option; - /*option = $('').attr({ - type: 'hidden', - id: 'edit-menu-item-title-'+item, - name: 'menu-item-title['+item+']', - value: off_canvas_control_data.title - }); - $(this).append(option);*/ + // Remove default fields we don't need + $this.children('p.field-url, p.field-link-target, .field-xfn, .field-description').remove(); + // Change description width. + $this.children('p.field-css-classes').removeClass('description-thin').addClass('description-wide'); - option = $('').attr({ - type: 'hidden', - id: 'edit-menu-item-url-'+item, - name: 'menu-item-url['+item+']', - value: '#off_canvas_control' - }); - $(this).append(option); + option = $('').attr( { + type: 'hidden', + id: 'edit-menu-item-url-' + item, + name: 'menu-item-url[' + item + ']', + value: '#off_canvas_control' + } ); + $this.append( option ); // a hidden field which exits only if our jQuery code has been executed - option = $('').attr({ - type: 'hidden', - id: 'edit-menu-item-off-canvas-control-detect-'+item, - name: 'menu-item-off-canvas-control-detect['+item+']', - value: 1 - }); - $(this).append(option); + option = $('').attr( { + type: 'hidden', + id: 'edit-menu-item-off-canvas-control-detect-' + item, + name: 'menu-item-off-canvas-control-detect[' + item + ']', + value: 1 + } ); + $this.append( option ); - o = ''; - o += '

'+strings.menu_item_type+'
'; - controls = off_canvas_control_data.controls; - for (var key in controls) { + var o = ''; + o += '

' + strings.menu_item_type + '
'; + for ( var key in controls ) { + if ( ! controls.hasOwnProperty( key ) ) { + continue; + } var checked = ''; - if ((typeof(off_canvas_control_data.val[item]) != 'undefined' && off_canvas_control_data.val[item]['off-canvas-control'] == key)) { + if (( 'undefined' !== typeof ocsNavControl.val[ item ] && key === ocsNavControl.val[ item ]['off-canvas-control'] ) ) { checked = ' checked="checked"'; } - o += ' '; - o += '
'; - }; + o += ' '; + o += '
'; + } o += '

'; - $(this).prepend(o); + $this.prepend( o ); - // Of only one sidebar is available, allways select its control - if ($(this).children('p.field-off-canvas-control').find('input[type="radio"]').length == 1) { - $(this).children('p.field-off-canvas-control').find('input[type="radio"]').prop('checked', true); - } - /* - ids = Array('menu_item_type'); // reverse order - // add the fields - for(var i = 0; i < ids.length; i++) { - p = $('

').attr('class', 'description'); - $(this).prepend(p); - label = $('

'+strings.menu_item_type+"
";for(var key in controls){if(!controls.hasOwnProperty(key)){continue}var checked="";if("undefined"!==typeof ocsNavControl.val[item]&&key===ocsNavControl.val[item]["off-canvas-control"]){checked=' checked="checked"'}o+=' ";o+='
"}o+="

";$this.prepend(o);var $field_control_options=$this.children("p.field-off-canvas-control").find('input[type="radio"]');if(1===$field_control_options.length){$field_control_options.prop("checked",true)}})}})}); \ No newline at end of file diff --git a/js/off-canvas-sidebars-settings.js b/js/off-canvas-sidebars-settings.js index a4a25d7..0b8f7b3 100644 --- a/js/off-canvas-sidebars-settings.js +++ b/js/off-canvas-sidebars-settings.js @@ -1,182 +1,208 @@ ;/** - * Off-Canvas Sidebars plugin + * Off-Canvas Sidebars plugin settings * - * OCS_OFF_CANVAS_SIDEBARS_SETTINGS * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3 + * @version 0.4 + * @global ocsOffCanvasSidebarsSettings + * @preserve */ -if ( typeof OCS_OFF_CANVAS_SIDEBARS_SETTINGS == 'undefined' ) { - var OCS_OFF_CANVAS_SIDEBARS_SETTINGS = { - 'general_key': 'off_canvas_sidebars_options', - 'plugin_key': 'off-canvas-sidebars-settings', - '__required_fields_not_set': '' //Some required fields are not set! +if ( 'undefined' === typeof ocsOffCanvasSidebarsSettings ) { + var ocsOffCanvasSidebarsSettings = { + general_key: 'off_canvas_sidebars_options', + plugin_key: 'off-canvas-sidebars-settings', + css_prefix: 'ocs', + __required_fields_not_set: 'Some required fields are not set!' }; } -(function($) { +( function( $ ) { - OCS_OFF_CANVAS_SIDEBARS_SETTINGS.init = function() { + var $document = $(document); + ocsOffCanvasSidebarsSettings.init = function() { var tab = $('#ocs_tab'); var postbox = $('.postbox'); - // close postboxes that should be closed + // Close postboxes that should be closed. $('.if-js-closed').removeClass('if-js-closed').addClass('closed'); - // postboxes setup - postboxes.add_postbox_toggles( OCS_OFF_CANVAS_SIDEBARS_SETTINGS.plugin_key ); + // Postboxes setup. + postboxes.add_postbox_toggles( ocsOffCanvasSidebarsSettings.plugin_key ); - if ( tab.val() == 'ocs-sidebars' ) { + if ( 'ocs-sidebars' === tab.val() ) { postbox.each( function() { - var sidebar_id = $(this).attr('id').replace('section_sidebar_', ''); + var prefix = 'off_canvas_sidebars_options_sidebars_', + sidebar_id = $(this).attr('id').replace('section_sidebar_', ''), + sidebar_prefix = prefix + sidebar_id; - ocs_show_hide_options_radio( '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_background_color_type', '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_background_color_wrapper', 'color', false ); + ocs_show_hide_options_radio( + '.' + sidebar_prefix + '_background_color_type', + '.' + sidebar_prefix + '_background_color_wrapper', + 'color', + false + ); + ocs_show_hide_options_radio( + '.' + sidebar_prefix + '_location', + '#' + sidebar_prefix + '_style_reveal, #' + sidebar_prefix + '_style_shift', + [ 'left', 'right' ], + 'label' + ); - ocs_show_hide_options( '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_overwrite_global_settings', '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_site_close', 'tr' ); - ocs_show_hide_options( '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_overwrite_global_settings', '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_disable_over', 'tr' ); - ocs_show_hide_options( '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_overwrite_global_settings', '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_hide_control_classes', 'tr' ); - ocs_show_hide_options( '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_overwrite_global_settings', '.off_canvas_sidebars_options_sidebars_' + sidebar_id + '_scroll_lock', 'tr' ); + ocs_show_hide_options( '.' + sidebar_prefix + '_overwrite_global_settings', '.' + sidebar_prefix + '_site_close', 'tr' ); + ocs_show_hide_options( '.' + sidebar_prefix + '_overwrite_global_settings', '.' + sidebar_prefix + '_disable_over', 'tr' ); + ocs_show_hide_options( '.' + sidebar_prefix + '_overwrite_global_settings', '.' + sidebar_prefix + '_hide_control_classes', 'tr' ); + ocs_show_hide_options( '.' + sidebar_prefix + '_overwrite_global_settings', '.' + sidebar_prefix + '_scroll_lock', 'tr' ); } ); } else { - ocs_show_hide_options_radio( '.off_canvas_sidebars_options_background_color_type', '.off_canvas_sidebars_options_background_color_wrapper', 'color' ); + ocs_show_hide_options_radio( + '.off_canvas_sidebars_options_background_color_type', + '.off_canvas_sidebars_options_background_color_wrapper', + 'color', + false + ); } - + /** + * Auto show/hide handler for checkbox elements. + * @todo Rename? + * @param {string} trigger The trigger element selector. + * @param {string} target The target element selector. + * @param {string|boolean|null} parent The parent element selector. + * @return {null} Nothing. + */ function ocs_show_hide_options( trigger, target, parent ) { - if ( ! $(trigger).is(':checked') ) { - if ( parent ) { - $(target).closest(parent).slideUp('fast'); - } else { - $(target).slideUp('fast'); - } + if ( parent ) { + target = $( target ).closest( parent ); } - $(trigger).change( function() { + if ( ! $( trigger ).is(':checked') ) { + $( target ).slideUp('fast'); + } + $( trigger ).change( function() { if ( $(this).is(':checked') ) { - if ( parent ) { - $(target).closest(parent).slideDown('fast'); - } else { - $(target).slideDown('fast'); - } + $( target ).slideDown('fast'); } else { - if ( parent ) { - $(target).closest(parent).slideUp('fast'); - } else { - $(target).slideUp('fast'); - } + $( target ).slideUp('fast'); } - }); + } ); } + /** + * Auto show/hide handler for radio elements. + * @param {string} trigger The trigger element selector. + * @param {string} target The target element selector. + * @param {string|object} compare The compare value. + * @param {string|boolean|null} parent The parent element selector. + * @return {null} Nothing. + */ function ocs_show_hide_options_radio( trigger, target, compare, parent ) { - if ( $(trigger).val() != compare ) { - if ( parent ) { - $(target).closest(parent).slideUp('fast'); - } else { - $(target).slideUp('fast'); - } + if ( ! $.isArray( compare ) ) { + compare = [ compare ]; } - $(trigger).change( function() { - if ($(this).val() == compare) { - if ( parent ) { - $(target).closest(parent).slideDown('fast'); - } else { - $(target).slideDown('fast'); - } + if ( parent ) { + parent += ', ' + parent + ' + br'; + target = $( target ).closest( parent ); + } + $( trigger ).change( function() { + if ( 0 <= $.inArray( $( trigger + ':checked' ).val(), compare ) ) { + $( target ).slideDown('fast'); } else { - if ( parent ) { - $(target).closest(parent).slideUp('fast'); - } else { - $(target).slideUp('fast'); - } + $( target ).slideUp('fast'); } - }); + } ).trigger( 'change' ); } - // Enable the WP Color Picker + // Enable the WP Color Picker. $('input.color-picker').wpColorPicker(); - // Validate required fields - $('input.required').each(function(){ - $(this).on('change', function() { - if ( $(this).val() == '' ) { - $(this).parents('tr').addClass('form-invalid'); + // Validate required fields. + $('input.required').each( function() { + var $this = $(this); + $this.on( 'change', function() { + if ( ! $this.val() ) { + $this.parents('tr').addClass('form-invalid'); } else { - $(this).parents('tr').removeClass('form-invalid'); + $this.parents('tr').removeClass('form-invalid'); } - }); - }); + } ); + } ); - // Validate form submit - $('#' + OCS_OFF_CANVAS_SIDEBARS_SETTINGS.general_key).submit( function(e) { + // Validate form submit. + $( '#' + ocsOffCanvasSidebarsSettings.general_key ).submit( function( e ) { var valid = true; //var errors = {}; - $('input.required', this).each(function(){ - if ( $(this).val() == '' ) { + $( 'input.required', this ).each( function() { + if ( ! $(this).val() ) { $(this).trigger('change'); valid = false; } - }); + } ); if ( ! valid ) { e.preventDefault(); - alert( OCS_OFF_CANVAS_SIDEBARS_SETTINGS.__required_fields_not_set ); + alert( ocsOffCanvasSidebarsSettings.__required_fields_not_set ); } } ); - if ( tab.val() == 'ocs-sidebars' ) { + if ( 'ocs-sidebars' === tab.val() ) { - // Dynamic sidebar ID + // Dynamic sidebar ID. if ( $('.js-dynamic-id').length ) { - postbox.each(function() { + postbox.each( function() { var sidebar = this; - $('.js-dynamic-id', sidebar).text( $('input.off_canvas_sidebars_options_sidebars_id', sidebar).val() ); + $( '.js-dynamic-id', sidebar ).text( $( 'input.off_canvas_sidebars_options_sidebars_id', sidebar ).val() ); $('.sidebar_classes').show(); - $('input.off_canvas_sidebars_options_sidebars_id', this).on('keyup', function() { - $('.js-dynamic-id', sidebar).text( $(this).val() ); - }); - }); + $( 'input.off_canvas_sidebars_options_sidebars_id', this ).on('keyup', function() { + $( '.js-dynamic-id', sidebar ).text( $(this).val() ); + } ); + } ); } - // Half opacity for closed disabled sidebars - postbox.each(function(){ - var sidebar = this; - $(sidebar).css({'border-left':'5px solid #eee'}); - if ( ! $('input.off_canvas_sidebars_options_sidebars_enable', sidebar).is(':checked') ) { - if ( $(sidebar).hasClass('closed') ) { - $(sidebar).css('opacity', '0.75'); + // Half opacity for closed disabled sidebars. + // @todo Use classes instead of CSS. + postbox.each( function() { + var sidebar = this, + $sidebar = $( sidebar ); + + $sidebar.css({'border-left':'5px solid #eee'}); + if ( ! $( 'input.off_canvas_sidebars_options_sidebars_enable', sidebar ).is(':checked') ) { + if ( $sidebar.hasClass('closed') ) { + $sidebar.css('opacity', '0.75'); } - $(sidebar).css('border-left-color','#ffb900'); + $sidebar.css('border-left-color','#ffb900'); } else { - $(sidebar).css('border-left-color','#46b450'); + $sidebar.css('border-left-color','#46b450'); } - $('input.off_canvas_sidebars_options_sidebars_enable', sidebar).on('change', function() { + $( 'input.off_canvas_sidebars_options_sidebars_enable', sidebar ).on( 'change', function() { if ( ! $(this).is(':checked') ) { - $(sidebar).css('border-left-color','#ffb900'); - if ( $(sidebar).hasClass('closed') ) { - $(sidebar).css('opacity', '0.75'); + $sidebar.css('border-left-color','#ffb900'); + if ( $sidebar.hasClass('closed') ) { + $sidebar.css('opacity', '0.75'); } else { - $(sidebar).css('opacity', ''); + $sidebar.css('opacity', ''); } } else { - $(sidebar).css('border-left-color','#46b450'); - $(sidebar).css('opacity', ''); + $sidebar.css('border-left-color','#46b450'); + $sidebar.css('opacity', ''); } - }); - $(sidebar).on('click', function() { - if ( ! $('input.off_canvas_sidebars_options_sidebars_enable', sidebar).is(':checked') && $(sidebar).hasClass('closed') ) { - $(sidebar).css('opacity', '0.75'); + } ); + $sidebar.on('click', function() { + if ( ! $( 'input.off_canvas_sidebars_options_sidebars_enable', sidebar ).is(':checked') && $sidebar.hasClass('closed') ) { + $sidebar.css('opacity', '0.75'); } else { - $(sidebar).css('opacity', ''); + $sidebar.css('opacity', ''); } - }); - }); + } ); + } ); - // Hide options when set to delete - $(document).on( 'change', '.off_canvas_sidebars_options_sidebars_delete', function() { - var sidebar = $(this).parents('.postbox'); - if ( $(this).is(':checked') ) { - var parent_row = $(this).parents('tr'); + // Hide options when set to delete. + $document.on( 'change', '.off_canvas_sidebars_options_sidebars_delete', function() { + var $this = $(this), + sidebar = $this.parents('.postbox'), + $sidebar = $( sidebar ); + + if ( $this.is(':checked') ) { + var parent_row = $this.parents('tr'); $( 'tr', sidebar ).hide( 'fast', function() { $( 'tr', sidebar ).each(function(){ if ( $(this).is( parent_row ) ) { @@ -184,10 +210,10 @@ if ( typeof OCS_OFF_CANVAS_SIDEBARS_SETTINGS == 'undefined' ) { } }); } ); - $(sidebar).css('opacity', '0.5'); - $(sidebar).css('border-left-color','#dc3232'); + $sidebar.css('opacity', '0.5'); + $sidebar.css('border-left-color','#dc3232'); } else { - $(sidebar).css('opacity', ''); + $sidebar.css('opacity', ''); $( 'tr', sidebar ).show( 'fast' ); $('input.off_canvas_sidebars_options_sidebars_enable', sidebar).trigger('change'); } @@ -195,8 +221,218 @@ if ( typeof OCS_OFF_CANVAS_SIDEBARS_SETTINGS == 'undefined' ) { } + if ( 'ocs-shortcode' === tab.val() ) { + + var fields = [ 'id', 'text', 'action', 'element', 'class', 'attr', 'nested' ]; + + for ( var i = 0, l = fields.length; i < l; i++ ) { + $( '#off_canvas_sidebars_options_' + fields[ i ] ).on( 'change keyup', function() { + create_shortcode(); + }); + } + + } + + /** + * Formats the data to a shortcode. + * @since 0.4 + * @return {null} Nothing. + */ + function create_shortcode() { + var field_data = {}; + for ( var i = 0, l = fields.length; i < l; i++ ) { + field_data[ fields[ i ] ] = $( '#off_canvas_sidebars_options_' + fields[ i ] ); + } + + var shortcode = 'ocs_trigger'; + + // Start the shortcode tag. + var shortcode_str = '[' + shortcode; + + // Loop through our known fields. + for ( var field in field_data ) { + if ( 'undefined' !== typeof field_data[ field ] ) { + if ( 'text' !== field && 'nested' !== field ) { + if ( field_data[ field ].is(':checked') ) { + shortcode_str += ' ' + field + '="1"'; + } else if ( field_data[ field ].val().length ) { + shortcode_str += ' ' + field + '="' + field_data[ field ].val().replace( /(\r\n|\n|\r)/gm, '' ) + '"'; + } + } + } + } + + // If the test contains a double quote, force it to be nested for compatibility. + if ( field_data.text.val().length && -1 < field_data.text.val().indexOf( '"' ) ) { + field_data.nested = true; + } + + // Add panel text. + if ( field_data.nested.is(':checked') ) { + shortcode_str += ']' + field_data.text.val() + '[/' + shortcode + ']'; + } else { + if ( field_data.text.val().length ) { + shortcode_str += ' text="' + field_data.text.val() + '"'; + } + shortcode_str += ']'; + } + + $('textarea#ocs_shortcode').val( shortcode_str ); + + create_shortcode_preview( field_data ); + } + + /** + * Parses the shortcode data for a HTML preview. + * @since 0.4 + * @param {object} field_data The shortcode data. + * @return {null} Nothing. + */ + function create_shortcode_preview( field_data ) { + + var element = ( field_data.element.val() ) ? field_data.element.val() : 'button', + attributes = ( field_data.attr.val() ) ? attrStringToObject( field_data.attr.val() ) : {}, + prefix = ocsOffCanvasSidebarsSettings.css_prefix, + action = ( field_data.action.val() ) ? field_data.action.val() : 'toggle', + classes = prefix + '-trigger ' + prefix + '-' + action, + singleton = false, + html = ''; + + if ( field_data.id.val() ) { + classes += ' ' + prefix + '-' + action + '-' + field_data.id.val(); + } + if ( field_data.class.val() ) { + classes += ' ' + field_data.class.val(); + } + if ( attributes.class ) { + classes += ' ' + attributes.class; + } + attributes.class = classes; + + if ( 'input' === element || 'img' === element ) { + singleton = true; + attributes.value = field_data.text.val(); + } + + if ( singleton ) { + html = '<' + element + ' ' + attrObjectToHTML( attributes ) + '>'; + } else { + html = '<' + element + ' ' + attrObjectToHTML( attributes ) + '>' + field_data.text.val() + ''; + } + + $( '#ocs_shortcode_preview' ).html( html ); + + $( '#ocs_shortcode_html' ).val( html ); + + } + + /** + * Convert HTML formatted attribute string to object. + * In: key="value" key="value" + * Out: { key: value, key: value } + * + * @since 0.4 + * @param {string} attrString The attribute string. + * @return {object} The attribute object. + */ + function attrHTMLToObject( attrString ) { + var arr = attrString.trim().split( '" ' ), + atts = {}; + for ( var key in arr ) { + if ( arr.hasOwnProperty( key ) ) { + arr[ key ] = arr[ key ].split( '="' ); + if ( arr[ key ][ 0 ].trim().length ) { + atts[ arr[ key ][ 0 ].trim() ] = getAttr( attrString, arr[ key ][ 0 ], false ); + } + } + } + return atts; + } + + /** + * Convert OCS formatted attribute string to object. + * + * In: key:value;key:value + * Out: { key: value, key: value } + * + * @since 0.4 + * @param {string} attrString The attribute string. + * @return {object} The attribute object. + */ + function attrStringToObject( attrString ) { + var arr = attrString.split( ';' ), + atts = {}; + for ( var key in arr ) { + if ( arr.hasOwnProperty( key ) ) { + arr[ key ] = arr[ key ].split( ':' ); + if ( arr[ key ][ 0 ].trim().length ) { + var name = arr[ key ][ 0 ].trim(); + arr[ key ].splice( 0, 1 ); + atts[ name ] = arr[ key ].join( ':' ); + } + } + } + return atts; + } + + /** + * Convert object to OCS formatted attribute string. + * + * In: { key: value, key: value } + * Out: key="value" key="value" + * + * @since 0.4 + * @param {object} attrObj The attribute object. + * @return {string} The attribute string. + */ + function attrObjectToHTML( attrObj ) { + var atts = []; + for ( var name in attrObj ) { + if ( attrObj.hasOwnProperty( name ) ) { + atts.push( name + '="' + attrObj[ name ] + '"' ); + } + } + return atts.join( ' ' ); + } + + /** + * Convert object to HTML formatted attribute string. + * + * In: { key: value, key: value } + * Out: key:value;key:value + * + * @since 0.4 + * @param {object} attrObj The attribute object. + * @return {string} The attribute string. + */ + function attrObjectToString( attrObj ) { + var atts = []; + for ( var name in attrObj ) { + if ( attrObj.hasOwnProperty( name ) ) { + atts.push( name + ':' + attrObj[ name ] ); + } + } + return atts.join( ';' ); + } + + /** + * @since 0.4 + * @param {string} s The string. + * @param {string} a The attribute to find. + * @param {boolean} f @todo + * @return {string|boolean} The attribute value or false. + */ + function getAttr( s, a, f ) { + var n = new RegExp( a + '=\"([^\"]+)\"', 'g' ).exec( s ); + if ( true === f && !n && -1 === s.indexOf( a + '="' ) ) { + // Attribute does not exist + return false; + } + return n ? window.decodeURIComponent( n[ 1 ] ).trim() : ''; + } + }; - OCS_OFF_CANVAS_SIDEBARS_SETTINGS.init(); + ocsOffCanvasSidebarsSettings.init(); -})(jQuery); \ No newline at end of file +} ) ( jQuery ); \ No newline at end of file diff --git a/js/off-canvas-sidebars-settings.min.js b/js/off-canvas-sidebars-settings.min.js new file mode 100644 index 0000000..721db1b --- /dev/null +++ b/js/off-canvas-sidebars-settings.min.js @@ -0,0 +1,10 @@ +;/** + * Off-Canvas Sidebars plugin settings + * + * @author Jory Hogeveen + * @package off-canvas-sidebars + * @version 0.4 + * @global ocsOffCanvasSidebarsSettings + * @preserve + */ +if("undefined"===typeof ocsOffCanvasSidebarsSettings){var ocsOffCanvasSidebarsSettings={general_key:"off_canvas_sidebars_options",plugin_key:"off-canvas-sidebars-settings",css_prefix:"ocs",__required_fields_not_set:"Some required fields are not set!"}}(function($){var $document=$(document);ocsOffCanvasSidebarsSettings.init=function(){var tab=$("#ocs_tab");var postbox=$(".postbox");$(".if-js-closed").removeClass("if-js-closed").addClass("closed");postboxes.add_postbox_toggles(ocsOffCanvasSidebarsSettings.plugin_key);if("ocs-sidebars"===tab.val()){postbox.each(function(){var prefix="off_canvas_sidebars_options_sidebars_",sidebar_id=$(this).attr("id").replace("section_sidebar_",""),sidebar_prefix=prefix+sidebar_id;ocs_show_hide_options_radio("."+sidebar_prefix+"_background_color_type","."+sidebar_prefix+"_background_color_wrapper","color",false);ocs_show_hide_options_radio("."+sidebar_prefix+"_location","#"+sidebar_prefix+"_style_reveal, #"+sidebar_prefix+"_style_shift",["left","right"],"label");ocs_show_hide_options("."+sidebar_prefix+"_overwrite_global_settings","."+sidebar_prefix+"_site_close","tr");ocs_show_hide_options("."+sidebar_prefix+"_overwrite_global_settings","."+sidebar_prefix+"_disable_over","tr");ocs_show_hide_options("."+sidebar_prefix+"_overwrite_global_settings","."+sidebar_prefix+"_hide_control_classes","tr");ocs_show_hide_options("."+sidebar_prefix+"_overwrite_global_settings","."+sidebar_prefix+"_scroll_lock","tr")})}else{ocs_show_hide_options_radio(".off_canvas_sidebars_options_background_color_type",".off_canvas_sidebars_options_background_color_wrapper","color",false)}function ocs_show_hide_options(trigger,target,parent){if(parent){target=$(target).closest(parent)}if(!$(trigger).is(":checked")){$(target).slideUp("fast")}$(trigger).change(function(){if($(this).is(":checked")){$(target).slideDown("fast")}else{$(target).slideUp("fast")}})}function ocs_show_hide_options_radio(trigger,target,compare,parent){if(!$.isArray(compare)){compare=[compare]}if(parent){parent+=", "+parent+" + br";target=$(target).closest(parent)}$(trigger).change(function(){if(0<=$.inArray($(trigger+":checked").val(),compare)){$(target).slideDown("fast")}else{$(target).slideUp("fast")}}).trigger("change")}$("input.color-picker").wpColorPicker();$("input.required").each(function(){var $this=$(this);$this.on("change",function(){if(!$this.val()){$this.parents("tr").addClass("form-invalid")}else{$this.parents("tr").removeClass("form-invalid")}})});$("#"+ocsOffCanvasSidebarsSettings.general_key).submit(function(e){var valid=true;$("input.required",this).each(function(){if(!$(this).val()){$(this).trigger("change");valid=false}});if(!valid){e.preventDefault();alert(ocsOffCanvasSidebarsSettings.__required_fields_not_set)}});if("ocs-sidebars"===tab.val()){if($(".js-dynamic-id").length){postbox.each(function(){var sidebar=this;$(".js-dynamic-id",sidebar).text($("input.off_canvas_sidebars_options_sidebars_id",sidebar).val());$(".sidebar_classes").show();$("input.off_canvas_sidebars_options_sidebars_id",this).on("keyup",function(){$(".js-dynamic-id",sidebar).text($(this).val())})})}postbox.each(function(){var sidebar=this,$sidebar=$(sidebar);$sidebar.css({"border-left":"5px solid #eee"});if(!$("input.off_canvas_sidebars_options_sidebars_enable",sidebar).is(":checked")){if($sidebar.hasClass("closed")){$sidebar.css("opacity","0.75")}$sidebar.css("border-left-color","#ffb900")}else{$sidebar.css("border-left-color","#46b450")}$("input.off_canvas_sidebars_options_sidebars_enable",sidebar).on("change",function(){if(!$(this).is(":checked")){$sidebar.css("border-left-color","#ffb900");if($sidebar.hasClass("closed")){$sidebar.css("opacity","0.75")}else{$sidebar.css("opacity","")}}else{$sidebar.css("border-left-color","#46b450");$sidebar.css("opacity","")}});$sidebar.on("click",function(){if(!$("input.off_canvas_sidebars_options_sidebars_enable",sidebar).is(":checked")&&$sidebar.hasClass("closed")){$sidebar.css("opacity","0.75")}else{$sidebar.css("opacity","")}})});$document.on("change",".off_canvas_sidebars_options_sidebars_delete",function(){var $this=$(this),sidebar=$this.parents(".postbox"),$sidebar=$(sidebar);if($this.is(":checked")){var parent_row=$this.parents("tr");$("tr",sidebar).hide("fast",function(){$("tr",sidebar).each(function(){if($(this).is(parent_row)){$(this).show("fast")}})});$sidebar.css("opacity","0.5");$sidebar.css("border-left-color","#dc3232")}else{$sidebar.css("opacity","");$("tr",sidebar).show("fast");$("input.off_canvas_sidebars_options_sidebars_enable",sidebar).trigger("change")}})}if("ocs-shortcode"===tab.val()){var fields=["id","text","action","element","class","attr","nested"];for(var i=0,l=fields.length;i"}else{html="<"+element+" "+attrObjectToHTML(attributes)+">"+field_data.text.val()+""}$("#ocs_shortcode_preview").html(html);$("#ocs_shortcode_html").val(html)}function attrHTMLToObject(attrString){var arr=attrString.trim().split('" '),atts={};for(var key in arr){if(arr.hasOwnProperty(key)){arr[key]=arr[key].split('="');if(arr[key][0].trim().length){atts[arr[key][0].trim()]=getAttr(attrString,arr[key][0],false)}}}return atts}function attrStringToObject(attrString){var arr=attrString.split(";"),atts={};for(var key in arr){if(arr.hasOwnProperty(key)){arr[key]=arr[key].split(":");if(arr[key][0].trim().length){var name=arr[key][0].trim();arr[key].splice(0,1);atts[name]=arr[key].join(":")}}}return atts}function attrObjectToHTML(attrObj){var atts=[];for(var name in attrObj){if(attrObj.hasOwnProperty(name)){atts.push(name+'="'+attrObj[name]+'"')}}return atts.join(" ")}function attrObjectToString(attrObj){var atts=[];for(var name in attrObj){if(attrObj.hasOwnProperty(name)){atts.push(name+":"+attrObj[name])}}return atts.join(";")}function getAttr(s,a,f){var n=new RegExp(a+'="([^"]+)"',"g").exec(s);if(true===f&&!n&&-1===s.indexOf(a+'="')){return false}return n?window.decodeURIComponent(n[1]).trim():""}};ocsOffCanvasSidebarsSettings.init()})(jQuery); \ No newline at end of file diff --git a/js/off-canvas-sidebars.js b/js/off-canvas-sidebars.js index 6fa90b6..758a993 100644 --- a/js/off-canvas-sidebars.js +++ b/js/off-canvas-sidebars.js @@ -1,69 +1,53 @@ ;/** * Off-Canvas Sidebars plugin * - * ocsOffCanvasSidebars * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3 + * @version 0.4 * @global ocsOffCanvasSidebars + * @preserve */ -if ( typeof ocsOffCanvasSidebars == 'undefined' ) { +if ( 'undefined' === typeof ocsOffCanvasSidebars ) { var ocsOffCanvasSidebars = { - "site_close": true, - "disable_over": false, - "hide_control_classes": false, - "scroll_lock": false, - "css_prefix": 'ocs', - "sidebars": {} + site_close: true, + disable_over: false, + hide_control_classes: false, + scroll_lock: false, + legacy_css: false, + css_prefix: 'ocs', + sidebars: {}, + _debug: false }; } -(function($) { +( function( $ ) { + + var $document = $(document); + var $window = $(window); + var $html = $('html'); + var $body = $('body'); ocsOffCanvasSidebars.slidebarsController = false; ocsOffCanvasSidebars.useAttributeSettings = false; + ocsOffCanvasSidebars.container = false; ocsOffCanvasSidebars._touchmove = false; + ocsOffCanvasSidebars._toolbar = $body.hasClass('admin-bar'); ocsOffCanvasSidebars.init = function() { /** - * Function call before initializing - * @since 0.3 - */ - if ( typeof ocsBeforeInitHook == 'function' ) { - ocsBeforeInitHook(); - } - - // Slidebars constructor - ocsOffCanvasSidebars.slidebarsController = new slidebars(); - - if ( false === ocsOffCanvasSidebars.slidebarsController ) { - return; - } - // Initialize slidebars - ocsOffCanvasSidebars.slidebarsController.init(); - - /** - * Function call after initializing - * @since 0.3 - */ - if ( typeof ocsAfterInitHook == 'function' ) { - ocsAfterInitHook(); - } - - /** - * Validate the disable_over setting ( using _getSetting() ) - - * Internal function, do not overwrite - + * Validate the disable_over setting ( using _getSetting() ). + * Internal function, do not overwrite. * @since 0.3 + * @param {string} sidebarId The sidebar ID. + * @return {boolean} disableOver status. */ ocsOffCanvasSidebars._checkDisableOver = function( sidebarId ) { var check = true; var disableOver = parseInt( ocsOffCanvasSidebars._getSetting( 'disable_over', sidebarId ) ); if ( disableOver && ! isNaN( disableOver ) ) { - if ( $( window ).width() > disableOver ) { + if ( $window.width() > disableOver ) { check = false; } } @@ -71,18 +55,25 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { }; /** - * Get the global setting or the sidebar setting (if set to overwrite) - - * Internal function, do not overwrite - + * Get the global setting or the sidebar setting (if set to overwrite). + * + * Internal function, do not overwrite. + * * @since 0.3 + * @param {string} key The setting key to look for. + * @param {string|boolean|null} sidebarId The sidebar ID. + * Pass `false` to check for an active slidebar. + * Pass `null` or no value for only the global setting. + * @return {string|boolean} The setting or false. */ ocsOffCanvasSidebars._getSetting = function( key, sidebarId ) { var overwrite, setting; var prefix = ocsOffCanvasSidebars.css_prefix; - if ( ! sidebarId ) { - sidebarId = ocsOffCanvasSidebars.slidebarsController.getActiveSlidebar(); + if ( 'undefined' !== typeof sidebarId ) { + if ( ! sidebarId && null !== sidebarId ) { + sidebarId = ocsOffCanvasSidebars.slidebarsController.getActiveSlidebar(); + } } if ( sidebarId ) { @@ -97,13 +88,13 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } } - // Fallback/Overwrite to enable sidebar settings from available attributes + // Fallback/Overwrite to enable sidebar settings from available attributes. } else { var sidebarElement = $( '#' + sidebarId ); overwrite = sidebarElement.attr( 'ocs-overwrite_global_settings' ); - if ( typeof overwrite !== 'undefined' && overwrite ) { + if ( overwrite ) { setting = sidebarElement.attr( 'ocs-' + key ); - if ( typeof setting != 'undefined' ) { + if ( 'undefined' !== typeof setting ) { return setting; } else { return false; @@ -112,11 +103,11 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } } - if ( typeof ocsOffCanvasSidebars[ key ] != 'undefined' && ! ocsOffCanvasSidebars.useAttributeSettings ) { + if ( ocsOffCanvasSidebars.hasOwnProperty( key ) && ! ocsOffCanvasSidebars.useAttributeSettings ) { return ocsOffCanvasSidebars[ key ]; } else { setting = $( '#' + prefix + '-site' ).attr( 'ocs-' + key ); - if ( typeof setting != 'undefined' ) { + if ( 'undefined' !== typeof setting ) { return setting; } } @@ -124,28 +115,174 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { return false; }; - // Prevent swipe events to be seen as a click (bug in some browsers) - $( document ).on( 'touchmove', function() { + /** + * Get the value from the transform axis of an element. + * @param {string|object} obj The element. + * @param {string} axis The axis to get. + * @returns {number|float|null} The axis value or null. + */ + ocsOffCanvasSidebars._getTranslateAxis = function( obj, axis ) { + obj = $( obj ); + var transformMatrix = obj.css("-webkit-transform") || + obj.css("-moz-transform") || + obj.css("-ms-transform") || + obj.css("-o-transform") || + obj.css("transform"); + if ( transformMatrix ) { + var matrix = transformMatrix.replace(/[^0-9\-.,]/g, '').split(','); + var val = false; + switch ( axis ) { + case 'x': + val = matrix[12] || matrix[4]; //translate x. + break; + case 'y': + val = matrix[13] || matrix[5]; //translate y. + break; + case 'z': + val = matrix[14] || matrix[6]; //translate z. + break; + } + return parseFloat( val ); + } else { + return 0; + } + }; + + ocsOffCanvasSidebars.container = $( '[canvas=container]' ); + + $window.trigger( 'ocs_before', this ); + + // Slidebars constructor. + ocsOffCanvasSidebars.slidebarsController = new slidebars(); + + if ( false === ocsOffCanvasSidebars.slidebarsController ) { + return; + } + + // Legacy CSS mode? + if ( ocsOffCanvasSidebars.legacy_css ) { + ocsOffCanvasSidebars.slidebarsController.legacy = true; + $html.addClass('ocs-legacy'); + } + + $window.trigger( 'ocs_loaded', this ); + + // Initialize slidebars. + ocsOffCanvasSidebars.slidebarsController.init(); + + $html.addClass('ocs-initialized'); + + $window.trigger( 'ocs_initialized', this ); + + /** + * Compatibility with WP Admin Bar. + * @since 0.4 + */ + if ( ocsOffCanvasSidebars._toolbar ) { + $window.on('load resize', function() { + // Offset top = admin bar height + var bodyOffset = $body.offset(); + $( '.' + ocsOffCanvasSidebars.css_prefix + '-slidebar' ).each( function() { + // Top slidebars + if ( $(this).hasClass( 'ocs-location-top' ) ) { + $(this).css( 'margin-top', parseInt( $(this).css('margin-top').replace( 'px', '' ) ) + bodyOffset.top + 'px' ); + } + // Left/Right slidebars + else if ( $(this).hasClass( 'ocs-location-left' ) || $(this).hasClass( 'ocs-location-right' ) ) { + $(this).css( 'margin-top', bodyOffset.top + 'px' ); + } + } ); + } ); + } + + /** + * Fix position issues for fixed elements on slidebar animations. + * @since 0.4 + */ + $( ocsOffCanvasSidebars.slidebarsController.events ).on( 'opening opened closing closed', function( e, sidebar_id ) { + var slidebar = ocsOffCanvasSidebars.slidebarsController.getSlidebar( sidebar_id ); + var duration = parseFloat( slidebar.element.css( 'transitionDuration' )/*, 10*/ ) * 1000; + if ( 'top' === slidebar.side || 'bottom' === slidebar.side ) { + var elements = ocsOffCanvasSidebars.getFixedElements(); + elements.attr( { 'canvas-fixed': 'fixed' } ); + + // Legacy mode (only needed for location: top). + // @todo, temp apply for reveal aswell + if ( ocsOffCanvasSidebars.legacy_css && 'top' === slidebar.side && ( 'overlay' !== slidebar.style && 'reveal' !== slidebar.style ) ) { + var offset; + // @todo, temp apply for reveal, should be 0 + //if ( 'reveal' === slidebar.style ) { + //offset = 0; //parseInt( slidebar.element.css( 'height' ).replace('px', '') ); + //} else { + offset = parseInt( slidebar.element.css( 'margin-top' ).replace('px', '').replace('-', '') ); + //} + + //Compatibility with WP Admin Bar. + // @todo, condition for setting + if ( ocsOffCanvasSidebars._toolbar ) { + var bodyOffset = $body.offset(); + offset += bodyOffset.top; + } + + elements.each( function() { + var $this = $(this); + // Set animation. + if ( 'opening' === e.type ) { + ocsOffCanvasSidebars.cssCompat( $this, 'transition', 'top ' + duration + 'ms' ); + $this.css( 'top', parseInt( $this.css('top').replace('px', '') ) + offset + 'px' ); + } + // Remove animation. + else if ( 'closing' === e.type ) { + $this.css( 'top', parseInt( $this.css('top').replace('px', '') ) - offset + 'px' ); + setTimeout( function() { + ocsOffCanvasSidebars.cssCompat( $this, 'transition', '' ); + }, duration ); + } + } ); + } + // Normal mode (only sets a transition for use in fixed-scrolltop.js). + else { + elements.each( function() { + var $this = $(this); + //var curVal = ocsOffCanvasSidebars._getTranslateAxis( this, 'y' ); + //console.log( curVal ); + if ( 'opening' === e.type || 'closing' === e.type ) { + ocsOffCanvasSidebars.cssCompat( $this, 'transition', 'transform ' + duration + 'ms' ); + //$(this).css('transform', 'translate( 0px, ' + curVal + slidebar.element.height() + 'px )' ); + } else if ( 'opened' === e.type || 'closed' === e.type ) { + ocsOffCanvasSidebars.cssCompat( $this, 'transition', '' ); + } + } ); + } + $window.trigger( 'slidebar_event', [ e.type, slidebar ] ); + } + } ); + + // Prevent swipe events to be seen as a click (bug in some browsers). + $document.on( 'touchmove', function() { ocsOffCanvasSidebars._touchmove = true; } ); - $( document ).on( 'touchstart', function() { + $document.on( 'touchstart', function() { ocsOffCanvasSidebars._touchmove = false; } ); - // Validate type, this could be changed with the hooks - if ( typeof ocsOffCanvasSidebars.setupTriggers == 'function' ) { + // Validate type, this could be changed with the hooks. + if ( 'function' === typeof ocsOffCanvasSidebars.setupTriggers ) { ocsOffCanvasSidebars.setupTriggers(); } + + $window.trigger( 'ocs_after', this ); }; /** - * Set the default settings for sidebars if they are not found - + * Set the default settings for sidebars if they are not found. * @since 0.3 + * @param {string} sidebarId The sidebar ID. + * @return {null} Nothing. */ ocsOffCanvasSidebars.setSidebarDefaultSettings = function( sidebarId ) { - if ( typeof ocsOffCanvasSidebars.sidebars[ sidebarId ] == 'undefined' ) { + if ( 'undefined' === typeof ocsOffCanvasSidebars.sidebars[ sidebarId ] ) { ocsOffCanvasSidebars.sidebars[ sidebarId ] = { 'overwrite_global_settings': false, "site_close": ocsOffCanvasSidebars.site_close, @@ -156,80 +293,82 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } }; + /** + * Setup automatic trigger handling. + * @since 0.3 + * @return {null} Nothing. + */ ocsOffCanvasSidebars.setupTriggers = function() { - var controller = ocsOffCanvasSidebars.slidebarsController; - var prefix = ocsOffCanvasSidebars.css_prefix; + var controller = ocsOffCanvasSidebars.slidebarsController, + prefix = ocsOffCanvasSidebars.css_prefix, + sidebarElements = $( '.' + prefix + '-slidebar' ); - $( '.' + prefix + '-slidebar' ).each( function() { + sidebarElements.each( function() { var id = $( this ).attr( 'ocs-sidebar-id' ); ocsOffCanvasSidebars.setSidebarDefaultSettings( id ); /** - * Toggle the sidebar + * Toggle the sidebar. * @since 0.1 */ - $( document ).on( 'touchend click', '.' + prefix + '-toggle-' + id, function( e ) { - // Stop default action and bubbling + $document.on( 'touchend click', '.' + prefix + '-toggle-' + id, function( e ) { + // Stop default action and bubbling. e.stopPropagation(); e.preventDefault(); - // Prevent touch+swipe + // Prevent touch+swipe. if ( true === ocsOffCanvasSidebars._touchmove ) { return; } - // Toggle the slidebar with respect for the disable_over setting + // Toggle the slidebar with respect for the disable_over setting. if ( ocsOffCanvasSidebars._checkDisableOver( prefix + '-' + id ) ) { controller.toggle( prefix + '-' + id ); } } ); /** - * Open the sidebar + * Open the sidebar. * @since 0.3 */ - $( document ).on( 'touchend click', '.' + prefix + '-open-' + id, function( e ) { - // Stop default action and bubbling + $document.on( 'touchend click', '.' + prefix + '-open-' + id, function( e ) { + // Stop default action and bubbling. e.stopPropagation(); e.preventDefault(); - // Prevent touch+swipe + // Prevent touch+swipe. if ( true === ocsOffCanvasSidebars._touchmove ) { return; } - // Open the slidebar with respect for the disable_over setting + // Open the slidebar with respect for the disable_over setting. if ( ocsOffCanvasSidebars._checkDisableOver( prefix + '-' + id ) ) { controller.open( prefix + '-' + id ); } } ); /** - * Close the sidebar + * Close the sidebar. * @since 0.3 */ - $( document ).on( 'touchend click', '.' + prefix + '-close-' + id, function( e ) { - // Stop default action and bubbling + $document.on( 'touchend click', '.' + prefix + '-close-' + id, function( e ) { + // Stop default action and bubbling. e.stopPropagation(); e.preventDefault(); - // Prevent touch+swipe + // Prevent touch+swipe. if ( true === ocsOffCanvasSidebars._touchmove ) { return; } - // Close the slidebar, no need to check the disable_over setting since we're closing the slidebar - //if ( ocsOffCanvasSidebars._checkDisableOver( prefix + '-' + id ) ) { - controller.close( prefix + '-' + id ); - //} + controller.close( prefix + '-' + id ); } ); } ); - - // Close any - $( document ).on( 'touchend click', '.' + prefix + '-close-any', function( e ) { + // Close any. + $document.on( 'touchend click', '.' + prefix + '-close-any', function( e ) { if ( ocsOffCanvasSidebars._getSetting( 'site_close', false ) ) { e.preventDefault(); e.stopPropagation(); @@ -237,8 +376,14 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } } ); + // Close the slidebar after clicking a link. + $( 'a' ).not( '.' + prefix + '-trigger' ).on( 'touchend click', function() { + if ( ! $(this).parents( '.' + prefix + '-trigger' ).length ) { + controller.close(); + } + } ); - // Close Slidebars when clicking on a link within a slidebar + // Close Slidebars when clicking on a link within a slidebar. /*$( '[off-canvas] a' ).on( 'touchend click', function( e ) { e.preventDefault(); e.stopPropagation(); @@ -251,29 +396,32 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } ); } );*/ - - // Add close class to canvas container when Slidebar is opened + // Add close class to canvas container when Slidebar is opened. $( controller.events ).on( 'opening', function () { $( '[canvas]' ).addClass( prefix + '-close-any' ); + $html.addClass( 'ocs-sidebar-active' ); + if ( ocsOffCanvasSidebars._getSetting( 'scroll_lock', false ) ) { + $html.addClass( 'ocs-scroll-lock' ); + } } ); - // Add close class to canvas container when Slidebar is opened + // Add close class to canvas container when Slidebar is opened. $( controller.events ).on( 'closing', function () { $( '[canvas]' ).removeClass( prefix + '-close-any' ); + $html.removeClass( 'ocs-sidebar-active ocs-scroll-lock' ); } ); - - // Disable slidebars when the window is wider than the set width + // Disable slidebars when the window is wider than the set width. var disableOver = function() { var prefix = ocsOffCanvasSidebars.css_prefix; - $( '.' + prefix + '-slidebar' ).each( function() { + sidebarElements.each( function() { var id = $( this ).attr( 'ocs-sidebar-id' ); if ( ! ocsOffCanvasSidebars._checkDisableOver( prefix + '-' + id ) ) { if ( controller.isActiveSlidebar( prefix + '-' + id ) ) { controller.close(); } - // Hide control classes + // Hide control classes. if ( ocsOffCanvasSidebars._getSetting( 'hide_control_classes', prefix + '-' + id ) ) { $( '.' + prefix + '-toggle-' + id ).hide(); } @@ -284,21 +432,73 @@ if ( typeof ocsOffCanvasSidebars == 'undefined' ) { } ); }; disableOver(); - $( window ).on( 'resize', disableOver ); + $window.on( 'resize', disableOver ); - // Disable scrolling on active sidebar - $( '#' + prefix + '-site' ).on( 'scroll touchmove mousewheel', function( e ) { - if ( ocsOffCanvasSidebars._getSetting( 'scroll_lock' ) && false != controller.getActiveSlidebar() ) { + // Disable scrolling outside of active sidebar. + $( '#' + prefix + '-site' ).on( 'scroll touchmove mousewheel DOMMouseScroll', function( e ) { + //if ( ocsOffCanvasSidebars._getSetting( 'scroll_lock' ) && false != controller.getActiveSlidebar() ) { + if ( $html.hasClass( 'ocs-scroll-lock' ) ) { e.preventDefault(); e.stopPropagation(); return false; } } ); + // Disable scrolling site when scrolling inside active sidebar. + sidebarElements.on( 'scroll touchmove mousewheel DOMMouseScroll', function( e ) { + //if ( ocsOffCanvasSidebars._getSetting( 'scroll_lock', false ) ) { + if ( $html.hasClass( 'ocs-scroll-lock' ) ) { + var $this = $(this); + if ( 0 > e.originalEvent.deltaY ) { + // scrolling up. + return ( 0 < $this.scrollTop() ); + } else { + // scrolling down. + return ( $this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight ); + } + } + } ); + + /** + * @fixme Fix for reveal and shift styles when page does not have enough height. + * @since 0.4 + */ + $window.on( 'load resize', function() { + ocsOffCanvasSidebars.container.css( 'min-height', $window.innerHeight() - parseInt( $html.css('margin-top'), 10 ) ); + } ); + + }; + + /** + * Get all fixed elements within the canvas container. + * @since 0.4 + * @return {object} A jQuery selection of fixed elements. + */ + ocsOffCanvasSidebars.getFixedElements = function() { + return $('#' + ocsOffCanvasSidebars.css_prefix + '-site *').filter( function() { + return ( 'fixed' === $(this).css('position') ); + } ); + }; + + /** + * Automatically apply browser prefixes before setting CSS values. + * @since 0.4 + * @param {object} elem The element. + * @param {string} prop The CSS property. + * @param {string|number} value The CSS property value. + * @return {null} Nothing. + */ + ocsOffCanvasSidebars.cssCompat = function( elem, prop, value ) { + var data = {}; + data[ '-webkit-' + prop ] = value; + data[ '-moz-' + prop ] = value; + data[ '-o-' + prop ] = value; + data[ prop ] = value; + $( elem ).css( data ); }; - if ( $( '#' + ocsOffCanvasSidebars.css_prefix + '-site' ).length && ( typeof slidebars != 'undefined' ) ) { + if ( $( '#' + ocsOffCanvasSidebars.css_prefix + '-site' ).length && ( 'undefined' !== typeof slidebars ) ) { ocsOffCanvasSidebars.init(); } -}) (jQuery); \ No newline at end of file +} ) ( jQuery ); \ No newline at end of file diff --git a/js/off-canvas-sidebars.min.js b/js/off-canvas-sidebars.min.js new file mode 100644 index 0000000..de3853d --- /dev/null +++ b/js/off-canvas-sidebars.min.js @@ -0,0 +1,10 @@ +;/** + * Off-Canvas Sidebars plugin + * + * @author Jory Hogeveen + * @package off-canvas-sidebars + * @version 0.4 + * @global ocsOffCanvasSidebars + * @preserve + */ +if("undefined"===typeof ocsOffCanvasSidebars){var ocsOffCanvasSidebars={site_close:true,disable_over:false,hide_control_classes:false,scroll_lock:false,legacy_css:false,css_prefix:"ocs",sidebars:{},_debug:false}}(function($){var $document=$(document);var $window=$(window);var $html=$("html");var $body=$("body");ocsOffCanvasSidebars.slidebarsController=false;ocsOffCanvasSidebars.useAttributeSettings=false;ocsOffCanvasSidebars.container=false;ocsOffCanvasSidebars._touchmove=false;ocsOffCanvasSidebars._toolbar=$body.hasClass("admin-bar");ocsOffCanvasSidebars.init=function(){ocsOffCanvasSidebars._checkDisableOver=function(sidebarId){var check=true;var disableOver=parseInt(ocsOffCanvasSidebars._getSetting("disable_over",sidebarId));if(disableOver&&!isNaN(disableOver)){if($window.width()>disableOver){check=false}}return check};ocsOffCanvasSidebars._getSetting=function(key,sidebarId){var overwrite,setting;var prefix=ocsOffCanvasSidebars.css_prefix;if("undefined"!==typeof sidebarId){if(!sidebarId&&null!==sidebarId){sidebarId=ocsOffCanvasSidebars.slidebarsController.getActiveSlidebar()}}if(sidebarId){if(!$.isEmptyObject(ocsOffCanvasSidebars.sidebars)&&!ocsOffCanvasSidebars.useAttributeSettings){sidebarId=sidebarId.replace(prefix+"-","");if(ocsOffCanvasSidebars.sidebars[sidebarId].overwrite_global_settings){setting=ocsOffCanvasSidebars.sidebars[sidebarId][key];if(setting){return setting}else{return false}}}else{var sidebarElement=$("#"+sidebarId);overwrite=sidebarElement.attr("ocs-overwrite_global_settings");if(overwrite){setting=sidebarElement.attr("ocs-"+key);if("undefined"!==typeof setting){return setting}else{return false}}}}if(ocsOffCanvasSidebars.hasOwnProperty(key)&&!ocsOffCanvasSidebars.useAttributeSettings){return ocsOffCanvasSidebars[key]}else{setting=$("#"+prefix+"-site").attr("ocs-"+key);if("undefined"!==typeof setting){return setting}}return false};ocsOffCanvasSidebars._getTranslateAxis=function(obj,axis){obj=$(obj);var transformMatrix=obj.css("-webkit-transform")||obj.css("-moz-transform")||obj.css("-ms-transform")||obj.css("-o-transform")||obj.css("transform");if(transformMatrix){var matrix=transformMatrix.replace(/[^0-9\-.,]/g,"").split(",");var val=false;switch(axis){case"x":val=matrix[12]||matrix[4];break;case"y":val=matrix[13]||matrix[5];break;case"z":val=matrix[14]||matrix[6];break}return parseFloat(val)}else{return 0}};ocsOffCanvasSidebars.container=$("[canvas=container]");$window.trigger("ocs_before",this);ocsOffCanvasSidebars.slidebarsController=new slidebars;if(false===ocsOffCanvasSidebars.slidebarsController){return}if(ocsOffCanvasSidebars.legacy_css){ocsOffCanvasSidebars.slidebarsController.legacy=true;$html.addClass("ocs-legacy")}$window.trigger("ocs_loaded",this);ocsOffCanvasSidebars.slidebarsController.init();$html.addClass("ocs-initialized");$window.trigger("ocs_initialized",this);if(ocsOffCanvasSidebars._toolbar){$window.on("load resize",function(){var bodyOffset=$body.offset();$("."+ocsOffCanvasSidebars.css_prefix+"-slidebar").each(function(){if($(this).hasClass("ocs-location-top")){$(this).css("margin-top",parseInt($(this).css("margin-top").replace("px",""))+bodyOffset.top+"px")}else if($(this).hasClass("ocs-location-left")||$(this).hasClass("ocs-location-right")){$(this).css("margin-top",bodyOffset.top+"px")}})})}$(ocsOffCanvasSidebars.slidebarsController.events).on("opening opened closing closed",function(e,sidebar_id){var slidebar=ocsOffCanvasSidebars.slidebarsController.getSlidebar(sidebar_id);var duration=parseFloat(slidebar.element.css("transitionDuration"))*1e3;if("top"===slidebar.side||"bottom"===slidebar.side){var elements=ocsOffCanvasSidebars.getFixedElements();elements.attr({"canvas-fixed":"fixed"});if(ocsOffCanvasSidebars.legacy_css&&"top"===slidebar.side&&("overlay"!==slidebar.style&&"reveal"!==slidebar.style)){var offset;offset=parseInt(slidebar.element.css("margin-top").replace("px","").replace("-",""));if(ocsOffCanvasSidebars._toolbar){var bodyOffset=$body.offset();offset+=bodyOffset.top}elements.each(function(){var $this=$(this);if("opening"===e.type){ocsOffCanvasSidebars.cssCompat($this,"transition","top "+duration+"ms");$this.css("top",parseInt($this.css("top").replace("px",""))+offset+"px")}else if("closing"===e.type){$this.css("top",parseInt($this.css("top").replace("px",""))-offset+"px");setTimeout(function(){ocsOffCanvasSidebars.cssCompat($this,"transition","")},duration)}})}else{elements.each(function(){var $this=$(this);if("opening"===e.type||"closing"===e.type){ocsOffCanvasSidebars.cssCompat($this,"transition","transform "+duration+"ms")}else if("opened"===e.type||"closed"===e.type){ocsOffCanvasSidebars.cssCompat($this,"transition","")}})}$window.trigger("slidebar_event",[e.type,slidebar])}});$document.on("touchmove",function(){ocsOffCanvasSidebars._touchmove=true});$document.on("touchstart",function(){ocsOffCanvasSidebars._touchmove=false});if("function"===typeof ocsOffCanvasSidebars.setupTriggers){ocsOffCanvasSidebars.setupTriggers()}$window.trigger("ocs_after",this)};ocsOffCanvasSidebars.setSidebarDefaultSettings=function(sidebarId){if("undefined"===typeof ocsOffCanvasSidebars.sidebars[sidebarId]){ocsOffCanvasSidebars.sidebars[sidebarId]={overwrite_global_settings:false,site_close:ocsOffCanvasSidebars.site_close,disable_over:ocsOffCanvasSidebars.disable_over,hide_control_classes:ocsOffCanvasSidebars.hide_control_classes,scroll_lock:ocsOffCanvasSidebars.scroll_lock}}};ocsOffCanvasSidebars.setupTriggers=function(){var controller=ocsOffCanvasSidebars.slidebarsController,prefix=ocsOffCanvasSidebars.css_prefix,sidebarElements=$("."+prefix+"-slidebar");sidebarElements.each(function(){var id=$(this).attr("ocs-sidebar-id");ocsOffCanvasSidebars.setSidebarDefaultSettings(id);$document.on("touchend click","."+prefix+"-toggle-"+id,function(e){e.stopPropagation();e.preventDefault();if(true===ocsOffCanvasSidebars._touchmove){return}if(ocsOffCanvasSidebars._checkDisableOver(prefix+"-"+id)){controller.toggle(prefix+"-"+id)}});$document.on("touchend click","."+prefix+"-open-"+id,function(e){e.stopPropagation();e.preventDefault();if(true===ocsOffCanvasSidebars._touchmove){return}if(ocsOffCanvasSidebars._checkDisableOver(prefix+"-"+id)){controller.open(prefix+"-"+id)}});$document.on("touchend click","."+prefix+"-close-"+id,function(e){e.stopPropagation();e.preventDefault();if(true===ocsOffCanvasSidebars._touchmove){return}controller.close(prefix+"-"+id)})});$document.on("touchend click","."+prefix+"-close-any",function(e){if(ocsOffCanvasSidebars._getSetting("site_close",false)){e.preventDefault();e.stopPropagation();controller.close()}});$("a").not("."+prefix+"-trigger").on("touchend click",function(){if(!$(this).parents("."+prefix+"-trigger").length){controller.close()}});$(controller.events).on("opening",function(){$("[canvas]").addClass(prefix+"-close-any");$html.addClass("ocs-sidebar-active");if(ocsOffCanvasSidebars._getSetting("scroll_lock",false)){$html.addClass("ocs-scroll-lock")}});$(controller.events).on("closing",function(){$("[canvas]").removeClass(prefix+"-close-any");$html.removeClass("ocs-sidebar-active ocs-scroll-lock")});var disableOver=function(){var prefix=ocsOffCanvasSidebars.css_prefix;sidebarElements.each(function(){var id=$(this).attr("ocs-sidebar-id");if(!ocsOffCanvasSidebars._checkDisableOver(prefix+"-"+id)){if(controller.isActiveSlidebar(prefix+"-"+id)){controller.close()}if(ocsOffCanvasSidebars._getSetting("hide_control_classes",prefix+"-"+id)){$("."+prefix+"-toggle-"+id).hide()}}else{$("."+prefix+"-toggle-"+id).show()}})};disableOver();$window.on("resize",disableOver);$("#"+prefix+"-site").on("scroll touchmove mousewheel DOMMouseScroll",function(e){if($html.hasClass("ocs-scroll-lock")){e.preventDefault();e.stopPropagation();return false}});sidebarElements.on("scroll touchmove mousewheel DOMMouseScroll",function(e){if($html.hasClass("ocs-scroll-lock")){var $this=$(this);if(0>e.originalEvent.deltaY){return 0<$this.scrollTop()}else{return $this.scrollTop()+$this.innerHeight()<$this[0].scrollHeight}}});$window.on("load resize",function(){ocsOffCanvasSidebars.container.css("min-height",$window.innerHeight()-parseInt($html.css("margin-top"),10))})};ocsOffCanvasSidebars.getFixedElements=function(){return $("#"+ocsOffCanvasSidebars.css_prefix+"-site *").filter(function(){return"fixed"===$(this).css("position")})};ocsOffCanvasSidebars.cssCompat=function(elem,prop,value){var data={};data["-webkit-"+prop]=value;data["-moz-"+prop]=value;data["-o-"+prop]=value;data[prop]=value;$(elem).css(data)};if($("#"+ocsOffCanvasSidebars.css_prefix+"-site").length&&"undefined"!==typeof slidebars){ocsOffCanvasSidebars.init()}})(jQuery); \ No newline at end of file diff --git a/off-canvas-sidebars.php b/off-canvas-sidebars.php index 5b13221..806dee4 100644 --- a/off-canvas-sidebars.php +++ b/off-canvas-sidebars.php @@ -1,18 +1,26 @@ + * @package Off_Canvas_Sidebars + * @since 0.1 + * @version 0.4 + * @licence GPL-2.0+ + * @link https://github.com/JoryHogeveen/off-canvas-sidebars + * + * @wordpress-plugin + * Plugin Name: Off-Canvas Sidebars + * Description: Add off-canvas sidebars using the Slidebars jQuery plugin + * Plugin URI: https://wordpress.org/plugins/off-canvas-sidebars/ + * Version: 0.4 + * Author: Jory Hogeveen + * Author URI: http://www.keraweb.nl + * Text Domain: off-canvas-sidebars + * Domain Path: /languages/ + * License: GPL-2.0+ + * License URI: http://www.gnu.org/licenses/gpl-2.0.html + * GitHub Plugin URI: https://github.com/JoryHogeveen/off-canvas-sidebars + * + * @copyright 2015-2017 Jory Hogeveen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,12 +36,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. - * */ -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); +if ( ! defined( 'ABSPATH' ) ) { + die(); +} -define( 'OCS_PLUGIN_VERSION', '0.3.1.1' ); +define( 'OCS_PLUGIN_VERSION', '0.4' ); define( 'OCS_FILE', __FILE__ ); define( 'OCS_BASENAME', plugin_basename( OCS_FILE ) ); define( 'OCS_PLUGIN_DIR', plugin_dir_path( OCS_FILE ) ); @@ -50,7 +59,7 @@ final class OCS_Off_Canvas_Sidebars protected static $_instance = null; /** - * Plugin version + * Plugin version. * * @var string * @since 0.1 @@ -58,7 +67,7 @@ final class OCS_Off_Canvas_Sidebars protected $version = OCS_PLUGIN_VERSION; /** - * Database version + * Database version. * * @var string * @since 0.2 @@ -66,7 +75,7 @@ final class OCS_Off_Canvas_Sidebars protected $db_version = '0'; /** - * User ignore nag key + * User ignore nag key. * * @var string * @since 0.1 @@ -74,7 +83,7 @@ final class OCS_Off_Canvas_Sidebars protected $noticeKey = 'ocs_ignore_theme_compatibility_notice'; /** - * Current user object + * Current user object. * * @var object * @since 0.1 @@ -90,89 +99,91 @@ final class OCS_Off_Canvas_Sidebars protected $enable = false; /** - * Plugin key + * Plugin key. * - * @var bool + * @var string * @since 0.1 */ protected $plugin_key = 'off-canvas-sidebars-settings'; /** - * Plugin general settings key, also used as option key + * Plugin general settings key, also used as option key. * - * @var bool + * @var string * @since 0.1 */ protected $general_key = 'off_canvas_sidebars_options'; /** - * Plugin settings + * Plugin settings. * - * @var bool + * @var array * @since 0.1 */ - protected $general_settings = array(); + protected $settings = array(); /** - * Plugin settings + * Plugin settings. * - * @var bool + * @var array * @since 0.1 */ protected $general_labels = array(); /** - * Default settings + * Default settings. * - * @var bool + * @var array * @since 0.2 */ protected $default_settings = array( - 'db_version' => '0', - 'enable_frontend' => 1, - 'frontend_type' => 'action', - 'site_close' => 1, - 'disable_over' => '', - 'hide_control_classes' => 0, - 'scroll_lock' => 0, - 'background_color_type' => '', - 'background_color' => '', - 'website_before_hook' => 'website_before', - 'website_after_hook' => 'website_after', - 'use_fastclick' => 0, - 'compatibility_position_fixed' => 0, - 'css_prefix' => 'ocs', - 'sidebars' => array(), + 'db_version' => '0', + 'enable_frontend' => 1, + 'frontend_type' => 'action', + 'site_close' => 1, + 'disable_over' => '', + 'hide_control_classes' => 0, + 'scroll_lock' => 0, + 'background_color_type' => '', + 'background_color' => '', + 'website_before_hook' => 'website_before', + 'website_after_hook' => 'website_after', + 'use_fastclick' => 0, + 'compatibility_position_fixed' => 'none', + 'wp_editor_shortcode_rendering' => 0, + 'css_prefix' => 'ocs', + 'sidebars' => array(), ); /** - * Default sidebar settings + * Default sidebar settings. * - * @var bool + * @var array * @since 0.2 */ protected $default_sidebar_settings = array( - 'enable' => 0, - 'label' => '', - 'content' => 'sidebar', - 'location' => 'left', - 'style' => 'push', - 'size' => 'default', - 'size_input' => '', - 'size_input_type' => '%', - 'animation_speed' => '', - 'padding' => '', - 'background_color' => '', - 'background_color_type' => '', + 'enable' => 0, + 'label' => '', + 'content' => 'sidebar', + 'location' => 'left', + 'style' => 'push', + 'size' => 'default', + 'size_input' => '', + 'size_input_type' => '%', + 'animation_speed' => '', + 'padding' => '', + 'background_color' => '', + 'background_color_type' => '', + // Global overwrites. 'overwrite_global_settings' => 0, - 'site_close' => 1, - 'disable_over' => '', - 'hide_control_classes' => 0, - 'scroll_lock' => 0, + 'site_close' => 1, + 'disable_over' => '', + 'hide_control_classes' => 0, + 'scroll_lock' => 0, ); /** - * Init function to register plugin hook + * Init function to register plugin hook. * * @since 0.1 * @access private @@ -180,87 +191,96 @@ final class OCS_Off_Canvas_Sidebars private function __construct() { self::$_instance = $this; - // DB version for the current plugin version (only major version tags) + // DB version for the current plugin version (only major version tags). $this->db_version = substr( OCS_PLUGIN_VERSION, 0, 3 ); - $this->enable = true; // Added for possible use in future - if ( $this->enable == true ) { + $this->enable = true; // Added for possible use in future. + if ( true === $this->enable ) { // Lets start! add_action( 'init', array( $this, 'init' ) ); - // Load the OCS API - include_once 'includes/off-canvas-sidebars-api.class.php'; + // Load the OCS API. + include_once( OCS_PLUGIN_DIR . 'includes/api.php' ); - $this->general_settings = ( get_option( $this->general_key ) ) ? get_option( $this->general_key ) : array(); + $this->settings = (array) get_option( $this->general_key, array() ); $this->maybe_db_update(); - // Merge DB settings with default settings - $this->general_settings = $this->get_settings(); + // Merge DB settings with default settings. + $this->settings = $this->get_settings(); $this->general_labels = $this->get_general_labels(); - // Register the widget - include_once 'widgets/off-canvas-sidebars-widget.php'; - add_action( 'widgets_init', function() { - register_widget( 'OCS_Off_Canvas_Sidebars_Control_Widget' ); - } ); + // Register the widget. + include_once( OCS_PLUGIN_DIR . 'widgets/control-widget.php' ); + add_action( 'widgets_init', array( $this, 'widgets_init' ) ); - // Load menu-meta-box option - include_once 'includes/off-canvas-sidebars-menu-meta-box.class.php'; - OCS_Off_Canvas_Sidebars_Menu_Meta_box::get_instance(); + // Load menu-meta-box option. + include_once( OCS_PLUGIN_DIR . 'includes/class-menu-meta-box.php' ); + OCS_Off_Canvas_Sidebars_Menu_Meta_Box::get_instance(); } else { // Added for possible use in future add_action( 'admin_notices', array( $this, 'compatibility_notice' ) ); - add_action( 'wp_ajax_'.$this->noticeKey, array( $this, 'ignore_compatibility_notice' ) ); + add_action( 'wp_ajax_' . $this->noticeKey, array( $this, 'ignore_compatibility_notice' ) ); } } /** - * Init function/action to check current user, load nessesary data and classes, register hooks + * Init function/action to check current user, load nessesary data and classes, register hooks. * * @return void * @since 0.1 */ function init() { - // Get the current user + // Get the current user. //$this->curUser = wp_get_current_user(); - // Load translations + // Load translations. $this->load_textdomain(); - // Register the enabled sidebars + // Register the enabled sidebars. $this->register_sidebars(); if ( is_admin() ) { - // Load the admin - include_once 'includes/off-canvas-sidebars-settings.class.php'; + // Load the settings page. + include_once( OCS_PLUGIN_DIR . 'includes/class-form.php' ); + include_once( OCS_PLUGIN_DIR . 'includes/class-settings.php' ); OCS_Off_Canvas_Sidebars_Settings::get_instance(); - // Add settings link to plugins page + // Load the WP Editor shortcode generator. + include_once( OCS_PLUGIN_DIR . 'includes/class-editor-shortcode-generator.php' ); + OCS_Off_Canvas_Sidebars_Editor_Shortcode_Generator::get_instance(); + + // Add settings link to plugins page. add_filter( 'plugin_action_links', array( $this, 'add_settings_link' ), 10, 2 ); } else { - // If a sidebar is enabled, load the front-end - if ( $this->is_sidebar_enabled() ) { - include_once 'includes/off-canvas-sidebars-frontend.class.php'; - OCS_Off_Canvas_Sidebars_Frontend::get_instance(); - } + // If a sidebar is enabled, load the front-end. + include_once( OCS_PLUGIN_DIR . 'includes/class-frontend.php' ); + OCS_Off_Canvas_Sidebars_Frontend::get_instance(); } } /** - * Add notice when theme is not compatible - * Checks for version in the notice ignore meta value. If the version is the same (user has clicked ignore), then hide it + * Register widgets. + * @since 0.4 + */ + function widgets_init() { + register_widget( 'OCS_Off_Canvas_Sidebars_Control_Widget' ); + } + + /** + * Add notice when theme is not compatible. + * Checks for version in the notice ignore meta value. If the version is the same (user has clicked ignore), then hide it. * * @return void * @since 0.1 */ function compatibility_notice() { - if ( get_user_meta( $this->curUser->ID, $this->noticeKey, true ) != $this->version ) { + if ( get_user_meta( $this->curUser->ID, $this->noticeKey, true ) !== $this->version ) { $class = 'error notice is-dismissible'; $message = '' . __( 'Off-Canvas Sidebars', 'off-canvas-sidebars' ) . ': ' . $this->general_labels['compatibility_notice_theme']; $ignore = '' . __( 'Dismiss this notice.', 'off-canvas-sidebars' ) . ''; @@ -270,10 +290,10 @@ function compatibility_notice() { } /** - * AJAX handler - * Stores plugin version + * AJAX handler. + * Stores plugin version. * - * Store format: boolean + * Store format: `boolean` * * @since 0.1 */ @@ -283,17 +303,17 @@ function ignore_compatibility_notice() { } /** - * Merge database plugin settings with default settings + * Merge database plugin settings with default settings. * * @since 0.1 * @return array */ function get_settings() { - $settings = $this->general_settings; + $settings = $this->settings; - // Validate global settings + // Validate global settings. $settings = $this->validate_settings( $settings, $this->get_default_settings() ); - // Validate sidebar settings + // Validate sidebar settings. foreach ( $settings['sidebars'] as $sidebar_id => $sidebar_settings ) { $settings['sidebars'][ $sidebar_id ] = $this->validate_settings( $sidebar_settings, $this->get_default_sidebar_settings() ); } @@ -302,7 +322,7 @@ function get_settings() { } /** - * Validate setting keys + * Validate setting keys. * * @since 0.2 * @param array $settings @@ -325,47 +345,57 @@ function validate_settings( $settings, $defaults ) { } /** - * Returns the default settings + * Returns the default settings. * * @since 0.2 - * @return string + * @return array */ - function get_default_settings() { return $this->default_settings; } + function get_default_settings() { + return $this->default_settings; + } /** - * Returns the default sidebar_settings + * Returns the default sidebar_settings. * * @since 0.2 - * @return string + * @return array */ - function get_default_sidebar_settings() { return $this->default_sidebar_settings; } + function get_default_sidebar_settings() { + return $this->default_sidebar_settings; + } /** - * Returns the plugin version + * Returns the plugin version. * * @since 0.1.2 * @return string */ - function get_version() { return $this->version; } + function get_version() { + return $this->version; + } /** - * Returns the plugin key + * Returns the plugin key. * * @since 0.1 * @return string */ - function get_plugin_key() { return $this->plugin_key; } + function get_plugin_key() { + return $this->plugin_key; + } /** - * Returns the general key (plugin settings) + * Returns the general key (plugin settings). * * @since 0.1 * @return string */ - function get_general_key() { return $this->general_key; } + function get_general_key() { + return $this->general_key; + } /** - * Returns the general labels + * Returns the general labels. * * @since 0.1 * @return array @@ -373,57 +403,58 @@ function get_general_key() { return $this->general_key; } function get_general_labels() { return array( 'no_sidebars_available' => __( 'Please enable an off-canvas sidebar', 'off-canvas-sidebars' ), - 'compatibility_notice_theme' => sprintf( __( 'If this plugin is not working as it should then your theme might not be compatible with this plugin, please let me know!', 'off-canvas-sidebars' ), 'https://wordpress.org/support/plugin/off-canvas-sidebars' ), + // Translators: %s stands for the URL. + 'compatibility_notice_theme' => sprintf( __( 'If this plugin is not working as it should then your theme might not be compatible with this plugin, please let me know!', 'off-canvas-sidebars' ), 'https://github.com/JoryHogeveen/off-canvas-sidebars/issues' ), ); } /** - * Returns a sidebar key based on its label + * Returns a sidebar key based on its label. * * @since 0.1 * @param string $label * @return string $key */ function get_sidebar_key_by_label( $label ) { - foreach ( $this->general_settings['sidebars'] as $key => $value ) { - if ( $label == $value['label'] ) + foreach ( $this->settings['sidebars'] as $key => $value ) { + if ( $label === $value['label'] ) return $key; } return false; } /** - * Checks if a sidebar is enabled + * Checks if a sidebar is enabled. * * @since 0.1 * @return bool */ function is_sidebar_enabled() { - foreach ( $this->general_settings['sidebars'] as $key => $value ) { - if ( 1 == $value['enable'] ) + foreach ( $this->settings['sidebars'] as $key => $value ) { + if ( 1 === (int) $value['enable'] ) return true; } return false; } /** - * Register slidebar sidebars + * Register slidebar sidebars. * Also checks if theme is based on the Genesis Framework. * * @since 0.1 * @return void */ function register_sidebars() { - foreach ( $this->general_settings['sidebars'] as $sidebar_id => $sidebar_data ) { + foreach ( $this->settings['sidebars'] as $sidebar_id => $sidebar_data ) { - if ( 1 == $sidebar_data['enable'] ) { + if ( ! empty( $sidebar_data['enable'] ) ) { - if ( 'sidebar' == $sidebar_data['content'] ) { + if ( 'sidebar' === $sidebar_data['content'] ) { $args = array( //'id' => 'off-canvas-' . $sidebar_id, 'class' => 'off-canvas-sidebar', - 'name' => __( 'Off Canvas', 'off-canvas-sidebars' ) . ': ' . $this->general_settings['sidebars'][ $sidebar_id ]['label'], + 'name' => __( 'Off Canvas', 'off-canvas-sidebars' ) . ': ' . $this->settings['sidebars'][ $sidebar_id ]['label'], 'description' => __( 'This is a widget area that is used for off-canvas widgets.', 'off-canvas-sidebars' ), //'before_widget' => '
', //'after_widget' => '
', @@ -432,14 +463,14 @@ function register_sidebars() { ); /** - * Filter the register_sidebar arguments + * Filter the register_sidebar arguments. * * Please note that the ID will be overwritten! * * @since 0.3 * * @see https://codex.wordpress.org/Function_Reference/register_sidebar - * @see $default_sidebar_settings for the sidebar settings + * @see $default_sidebar_settings for the sidebar settings. * * @param array $args The register_sidebar() arguments * @param string $sidebar_id The ID of this sidebar as configured in: Appearances > Off-Canvas Sidebars > Sidebars @@ -450,26 +481,26 @@ function register_sidebars() { // Force our ID $args['id'] = 'off-canvas-' . $sidebar_id; - if ( get_template() == 'genesis' ) { + if ( get_template() === 'genesis' ) { genesis_register_sidebar( $args ); } else { register_sidebar( $args ); } } - elseif ( 'menu' == $sidebar_data['content'] ) { + elseif ( 'menu' === $sidebar_data['content'] ) { register_nav_menu( 'off-canvas-' . $sidebar_id, - __( 'Off Canvas', 'off-canvas-sidebars' ) . ': ' . $this->general_settings['sidebars'][ $sidebar_id ]['label'] + __( 'Off Canvas', 'off-canvas-sidebars' ) . ': ' . $this->settings['sidebars'][ $sidebar_id ]['label'] ); - } - } - } + } // End if(). + } // End if(). + } // End foreach(). } /** - * Add Settings link to plugin's entry on the Plugins page + * Add Settings link to plugin's entry on the Plugins page. * * @since 0.1 * @param array $links @@ -477,14 +508,10 @@ function register_sidebars() { * @return array */ function add_settings_link( $links, $file ) { - static $this_plugin; - if ( ! $this_plugin ) $this_plugin = OCS_BASENAME; - - if ( $file == $this_plugin ) { + if ( OCS_BASENAME === $file ) { $settings_link = '' . esc_attr__( 'Settings', 'off-canvas-sidebars' ) . ''; array_unshift( $links, $settings_link ); } - return $links; } @@ -498,30 +525,29 @@ function load_textdomain() { load_plugin_textdomain( 'off-canvas-sidebars', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); } - /** - * Update settings + * Update settings. * * @since 0.2 * @access private * @return void */ private function db_update() { - $settings = $this->general_settings; + $settings = $this->settings; $db_version = strtolower( $settings['db_version'] ); - // Compare versions - if ( version_compare( $db_version, '0.2', '<' ) ) { + // Upgrade to 0.2.x + if ( version_compare( $db_version, '0.2', '<' ) && isset( $settings['sidebars'] ) ) { foreach ( $settings['sidebars'] as $sidebar_id => $sidebar_data ) { if ( empty( $sidebar_data['label'] ) ) { - // Label is new + // @codingStandardsIgnoreLine - Label is new $settings['sidebars'][ $sidebar_id ]['label'] = __( ucfirst( $sidebar_id ), 'off-canvas-sidebars' ); // Location is new. In older versions the location was the sidebar_id (left or right) $settings['sidebars'][ $sidebar_id ]['location'] = $sidebar_id; if ( isset( $sidebar_data['width'] ) ) { - if ( $sidebar_data['width'] == 'thin' ) { + if ( 'thin' === $sidebar_data['width'] ) { $sidebar_data['width'] = 'small'; - } elseif ( $sidebar_data['width'] == 'wide' ) { + } elseif ( 'wide' === $sidebar_data['width'] ) { $sidebar_data['width'] = 'large'; } $settings['sidebars'][ $sidebar_id ]['size'] = $sidebar_data['width']; @@ -535,24 +561,39 @@ private function db_update() { } } } + + // Upgrade to 0.3.x if ( version_compare( $db_version, '0.3', '<' ) && version_compare( $db_version, '0', '>' ) ) { - $settings['css_prefix'] = 'sb'; // Old Slidebars classes + // Old Slidebars classes prefix. + $settings['css_prefix'] = 'sb'; + } + + // Upgrade to 0.4 + if ( version_compare( $db_version, '0.4', '<' ) ) { + if ( ! empty( $settings['compatibility_position_fixed'] ) ) { + // This was the only option before 0.4. + $settings['compatibility_position_fixed'] = 'custom-js'; + } } $settings['db_version'] = $this->db_version; update_option( $this->general_key, $settings ); - $this->general_settings = $settings; + $this->settings = $settings; } /** - * Check the correct DB version in the DB + * Check the correct DB version in the DB. * * @since 0.2 * @access public * @return void */ public function maybe_db_update() { - $db_version = strtolower( $this->general_settings['db_version'] ); + if ( ! isset( $this->settings['db_version'] ) ) { + $this->settings['db_version'] = 0; + $this->db_update(); + } + $db_version = strtolower( $this->settings['db_version'] ); if ( version_compare( $db_version, $this->db_version, '<' ) ) { $this->db_update(); } @@ -565,7 +606,7 @@ public function maybe_db_update() { * * @since 0.1.2 * @static - * @see Off_Canvas_Sidebars() + * @see off_canvas_sidebars() * @return OCS_Off_Canvas_Sidebars */ public static function get_instance() { @@ -621,8 +662,8 @@ public function __wakeup() { * * @since 0.3 * @access public - * @param string - * @param array + * @param string $method + * @param array $args * @return null */ public function __call( $method = '', $args = array() ) { @@ -635,7 +676,7 @@ public function __call( $method = '', $args = array() ) { return null; } -} // end class +} // End class(). /** * Main instance of Off-Canvas Sidebars. @@ -645,7 +686,7 @@ public function __call( $method = '', $args = array() ) { * @since 0.1.2 * @return OCS_Off_Canvas_Sidebars */ -function Off_Canvas_Sidebars() { +function off_canvas_sidebars() { return OCS_Off_Canvas_Sidebars::get_instance(); } -Off_Canvas_Sidebars(); +off_canvas_sidebars(); diff --git a/readme.txt b/readme.txt index 79be980..efe68d8 100644 --- a/readme.txt +++ b/readme.txt @@ -2,33 +2,42 @@ Contributors: keraweb Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=YGPLMLU7XQ9E8&lc=NL&item_name=Off%2dCanvas%20Sidebars&item_number=JWPP%2dOCS¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted Tags: genesis, off-canvas, menus, widgets, sidebars, slidebars, jQuery, app, mobile, tablet, responsive -Requires at least: 3.8 -Tested up to: 4.6 -Stable tag: 0.3.1.1 +Requires at least: 4.1 +Tested up to: 4.8 +Requires PHP: 5.2.4 +Stable tag: 0.4 Add off-canvas sidebars containing widgets, menus or other content using the Slidebars jQuery plugin. == Description == -This plugin will add various options to implement off-canvas sidebars in your WordPress theme using the Slidebars jQuery plugin. +This plugin will add various options to implement off-canvas sidebars in your WordPress theme based on the Slidebars jQuery plugin. = Overview / Features = * Add off-canvas sidebars to the left, right, top and bottom of your website * Use sidebar areas (widget-ready areas), menu locations or [custom hooks](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Actions-&-Filters) to place content into the off-canvas sidebars -* You can add control buttons with a widget, a menu item or with [custom code](https://wordpress.org/plugins/off-canvas-sidebars/installation/) +* You can add control buttons with a widget, menu item, [shortcode](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Shortcodes) or with [custom code](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) * Various customisation options and settings available in the Appearances menu = Compatibility (IMPORTANT!) = -The structure of your theme is of great importance for this plugin. Please read the [installation guide](https://wordpress.org/plugins/off-canvas-sidebars/installation/) carefully!! +The structure of your theme is of great importance for this plugin. Please read the [installation guide](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) carefully!! This plugin should work with most themes and plugins although I can't be sure for all use-cases. At this point it's still a 0.x version... If the plugin does not work for your theme, please let me know through the support and add a plugins and themes list and I will take a look! +**Fixed elements (like sticky menu's)** +There are known issues with fixed elements and Slidebars. [Click here for more information](https://www.adchsm.com/slidebars/help/advanced-usage/elements-with-fixed-positions/) +I've created two possible solutions for this: + +1. Legacy CSS solution. Use basic CSS2 positioning instead of CSS3 transform with hardware acceleration. +2. JavaScript solution. It is slower but still allows the use of hardware acceleration. + = It's not working! / I found a bug! = -Please let me know through the support and add a plugins and themes list! :) +Please let me know through [support](https://wordpress.org/support/plugin/off-canvas-sidebars) and add a plugins and themes list! :) +Or [submit an issue here on GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/issues) = Credits = @@ -45,119 +54,113 @@ Or search for "Off-Canvas Sidebars" via your plugins menu. = Theme Setup = -**Themes based on the Genesis Framework are supported by default! No changes needed.** - -*Please note that it is possible that there are some Genesis themes that can not be supported out-of-the-box due to their structure.* - -There are more themes with similar implementations like Genesis to insert code before and after the website HTML through actions hooks. These theme can most likely be supported without any changes. -[See a full list here with currently known themes](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Compatible-theme-hooks) - -**For other themes there are two options:** +Off-Canvas Sidebars won't work "out of the box" with most themes, please read the documentation! +[Click here for theme setup documentation.](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Theme-setup) -1. Simple theme setup -2. Custom theme setup +== Frequently Asked Questions == -= 1: Simple theme setup = += 1. Will this plugin work with any theme? = -*First of all, I strongly advice to create a child theme if you didn't already! [Click here for more information](https://codex.wordpress.org/Child_Themes "Click here for more information").* +No, due to the difference in structure not all theme's are compatible. +Though most themes can be *made* compatible with some modifications! -Add this code directly after the <body> tag. This is probably located in the header.php or index.php theme file. -`` += 2. Can I add as many sidebars as I like? = -Add this code directly after the site content, before the wp_footer() function. This is probably located in the footer.php or index.php theme file. -`` -*Important: This code needs to be a direct child of the <body> tag!* +Yes you can, keep in mind that the more sidebars you add the heaver the load is on the server (PHP) and browser (JS). -The final output of your theme should be similar to this: -` - - ** HEADER CONTENT ** - - - - ** WEBSITE CONTENT ** - - - -` += 3. How do I change the CSS for the sidebars? = -= 2: Custom theme setup = - -* Disable the front-end option in the settings page under the Appearances menu. -* Scripts and styles will still be included! -* [Click here for documentation on the Slidebars jQuery plugin](https://www.adchsm.com/slidebars/help/usage/). -* [Click here for the API and available actions and filters](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki) +This plugin only provides the framework that handles the off-canvas part. +There are some settings that slightly change the display but this is very limited. +For more advanced customisations either: +1. Edit your theme’s style.css file (usually located in `/wp-content/themes/YOURTHEME/`). +2. Use a plugin such as [Simple Custom CSS](https://wordpress.org/plugins/simple-custom-css/). == Screenshots == 1. Settings page 2. Sidebars settings page (sidebars closed) 3. Sidebars settings page (sidebar opened) -4. Control Widget -5. Menu item -6. Sidebar left (Push effect) -> image from Slidebars website -7. Sidebar left (Overlay effect) -> image from Slidebars website -8. Sidebar top (Push effect) -> image from Slidebars website +4. Shortcode generator page +5. Control Widget +6. Menu item +7. Sidebar left (Push effect) -> image from Slidebars website +8. Sidebar left (Overlay effect) -> image from Slidebars website +9. Sidebar top (Push effect) -> image from Slidebars website == Changelog == += 0.4 = +* **Feature:** `[ocs_trigger]` shortcode to display trigger buttons/elements anywhere you like, [click here for documentation](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/Shortcodes). [#24](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/24) + * Shortcode generator available in the settings page. + * Integrate a shortcode generator with the WP Editor. [#32](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/32) +* **Enhancement:** New "Legacy CSS" mode. Modified the Slidebars library to support older CSS2 animations. Can fix a lot of issues with fixed elements. [#26](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/26) +* **Compatibility:** Modified the default Slidebars CSS to support anchor links and common smooth scroll implementations. +* **Compatibility:** Some enhancements for compatibility with the WP Admin Bar. +* **UI:** Improve widget UI [#27](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/27) +* **Fix:** Enhance the codebase to be more aligned with the WP coding standards with CodeClimate. + +Detailed info: [PR on GitHub](https://github.com/JoryHogeveen/view-admin-as/pull/25) + = 0.3.1.1 = -* Fix: Settings page checkbox bug when saving +* **Fix:** Settings page checkbox bug when saving = 0.3.1 = -* Feature: Allow changing this plugin capability to show the settings page -* Fix: Update fixed element compat for the new Slidebars version (still experimental, Slidebars still doesn't fully support fixed elements within the site container) -* Fix: Don't echo empty sidebar CSS selectors if no styles are set -* UI: Set `.ocs-button` to `cursor: pointer;` by default +* **Feature:** Allow changing this plugin capability to show the settings page +* **Fix:** Update fixed element compat for the new Slidebars version (still experimental, Slidebars still doesn't fully support fixed elements within the site container) +* **Fix:** Don't echo empty sidebar CSS selectors if no styles are set +* **UI:** Set `.ocs-button` to `cursor: pointer;` by default * Update textdomain hook +Detailed info: [PR on GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/pull/23) + = 0.3 = -* Feature: Allow sidebars to overwrite some general settings -* Feature: Option to set padding to sidebars -* Feature: Option to choose other content types than only a WP sidebar for an off-canvas sidebar -* Feature: Option to set your own CSS prefix (some classes are fixes to `ocs` and can't be changed, the prefix `ocs` is also the default prefix for new installations) -* Feature: Added various actions, filters and JS hooks - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki) -* OCS API functions to output off canvas sidebars in your theme instead of using this plugin frontend functions - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/PHP-API) -* Fix: Sidebar ID validation wasn't correct +* **Feature:** Allow sidebars to overwrite some general settings +* **Feature:** Option to set padding to sidebars +* **Feature:** Option to choose other content types than only a WP sidebar for an off-canvas sidebar +* **Feature:** Option to set your own CSS prefix (some classes are fixes to `ocs` and can't be changed, the prefix `ocs` is also the default prefix for new installations) +* **Feature:** Added various actions, filters and JS hooks - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki) +* **Feature:** OCS API functions to output off canvas sidebars in your theme instead of using this plugin frontend functions - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/wiki/PHP-API) +* **Fix:** Sidebar ID validation wasn't correct Detailed info: [PR on GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/pull/10) = 0.2.2 = -* Feature: Option to set the animation speed for sidebars -* Feature: Option to use the FastClick library - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/9 "Click here for info") -* Fix: Disabling sidebars on global settings page didn't work +* **Feature:** Option to set the animation speed for sidebars +* **Feature:** Option to use the FastClick library - [Click here for info](https://github.com/JoryHogeveen/off-canvas-sidebars/issues/9 "Click here for info") +* **Fix:** Disabling sidebars on global settings page didn't work = 0.2.1 = -* Fix: Add touch events for iOS mobile device compatibility -* Added some actions for front-end (see Other Notes) +* **Fix:** Add touch events for iOS mobile device compatibility +* **Enhancement:** Added some actions for front-end (see Other Notes) = 0.2.0.1 = -* Fix: Global variable bug -* UI: Improve settings page +* **Fix:** Global variable bug +* **UI:** Improve settings page = 0.2 = * Update Slidebars plugin to v2.0.2: [click here for info](https://www.adchsm.com/slidebars/features/ "Slidebars Features") -* Feature: An unlimited amount of off-canvas sidebars (No longer just one left, one right) -* Feature: 2 new locations (top and bottom) -* Feature: 2 new effects (reveal and shift) -* UI: Improved settings pages -* I18n: Translations are now managed at [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/off-canvas-sidebars "translate.wordpress.org") +* **Feature:** An unlimited amount of off-canvas sidebars (No longer just one left, one right) +* **Feature:** 2 new locations (top and bottom) +* **Feature:** 2 new effects (reveal and shift) +* **UI:** Improved settings pages +* **I18n:** Translations are now managed at [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/off-canvas-sidebars "translate.wordpress.org") * Screenshots updated * Tested with WordPress 4.6 = 0.1.2 = -* Feature: First experiment for compatibility with fixed elements within the site container with the use of `transform: translateZ` (needed for `-webkit-` and `-moz-` only). [See problem here](http://stackoverflow.com/questions/2637058/positions-fixed-doesnt-work-when-using-webkit-transform "See problem here") -* Improvement: Usage of a single instance of the class +* **Feature:** First experiment for compatibility with fixed elements within the site container with the use of `transform: translateZ` (needed for `-webkit-` and `-moz-` only). [See problem here](http://stackoverflow.com/questions/2637058/positions-fixed-doesnt-work-when-using-webkit-transform "See problem here") +* **Improvement:** Usage of a single instance of the class = 0.1.1 = -* Feature: Added the option to change the website_before and website_after hook names +* **Feature:** Added the option to change the website_before and website_after hook names = 0.1 = @@ -165,7 +168,7 @@ Created from nothingness just to be one of the cool kids. Yay! == Other Notes == -You can find me here: += You can find me here: = * [GitHub](https://github.com/JoryHogeveen/off-canvas-sidebars/ "GitHub") * [Keraweb](http://www.keraweb.nl/ "Keraweb") @@ -185,5 +188,8 @@ Please let me know through the support page! == Upgrade Notice == += 0.4 = +Version 0.4 introduces some radical code changes to the plugin. Please clear your cache after updating + = 0.2 = Version 0.2 introduces some radical code changes to the plugin. Please clear your cache after updating diff --git a/slidebars/slidebars.css b/slidebars/slidebars.css index 40efd0d..3e41579 100644 --- a/slidebars/slidebars.css +++ b/slidebars/slidebars.css @@ -6,6 +6,11 @@ * Author url: http://www.adchsm.com/ * License: MIT * License url: http://www.adchsm.com/slidebars/license/ + * + * Modified by: Jory Hogeveen + * Version numbers below are related to Off-Canvas Sidebars, not Slidebars. + * + * @since 0.4 Enhance location selectors, added quotes. */ /** @@ -50,7 +55,7 @@ html, body { } /** - * Off-Canavs + * Off-Canvas */ [off-canvas] { @@ -63,45 +68,45 @@ html, body { -webkit-overflow-scrolling: touch; /* Enables momentum scrolling on iOS devices, may be removed by setting to 'auto' in your own CSS. */ } -[off-canvas*=top] { +[off-canvas*=" top"] { width: 100%; height: 255px; top: 0; } -[off-canvas*=right] { +[off-canvas*=" right"] { width: 255px; height: 100%; top: 0; right: 0; } -[off-canvas*=bottom] { +[off-canvas*=" bottom"] { width: 100%; height: 255px; bottom: 0; } -[off-canvas*=left] { +[off-canvas*=" left"] { width: 255px; height: 100%; top: 0; left: 0; } -[off-canvas*=reveal] { +[off-canvas*=" reveal"] { z-index: 0; } -[off-canvas*=push] { +[off-canvas*=" push"] { z-index: 1; } -[off-canvas*=overlay] { +[off-canvas*=" overlay"] { z-index: 9999; } -[off-canvas*=shift] { +[off-canvas*=" shift"] { z-index: 0; } @@ -118,22 +123,22 @@ html, body { -webkit-backface-visibility: hidden; /* Prevents flickering, may be removed if experiencing problems with fixed background images in Chrome. */ } -[off-canvas*=shift][off-canvas*=top] { +[off-canvas*=" shift"][off-canvas*=" top"] { -webkit-transform: translate( 0px, 50% ); transform: translate( 0px, 50% ); } -[off-canvas*=shift][off-canvas*=right] { +[off-canvas*=" shift"][off-canvas*=" right"] { -webkit-transform: translate( -50%, 0px ); transform: translate( -50%, 0px ); } -[off-canvas*=shift][off-canvas*=bottom] { +[off-canvas*=" shift"][off-canvas*=" bottom"] { -webkit-transform: translate( 0px, -50% ); transform: translate( 0px, -50% ); } -[off-canvas*=shift][off-canvas*=left] { +[off-canvas*=" shift"][off-canvas*=" left"] { -webkit-transform: translate( 50%, 0px ); transform: translate( 50%, 0px ); } diff --git a/slidebars/slidebars.js b/slidebars/slidebars.js index 25bf225..7e90d32 100644 --- a/slidebars/slidebars.js +++ b/slidebars/slidebars.js @@ -1,4 +1,4 @@ -;/*! +;/** * Slidebars - A jQuery Framework for Off-Canvas Menus and Sidebars * Version: 2.0.2 * Url: http://www.adchsm.com/slidebars/ @@ -6,16 +6,23 @@ * Author url: http://www.adchsm.com/ * License: MIT * License url: http://www.adchsm.com/slidebars/license/ - */ - -/*! + * * Modified by: Jory Hogeveen + * Version numbers and info below is related to Off-Canvas Sidebars, not Slidebars. + * + * @package off-canvas-slidebars + * @author Jory Hogeveen + * + * @version 0.4 + * @since 0.4 Add scope for this reference + Add legacy CSS support (no hardware acceleration) + * @global slidebars + * @preserve */ var slidebars; (function($) { - + slidebars = function () { /** @@ -28,6 +35,9 @@ slidebars = function () { // Object of Slidebars offCanvas = {}, + // Create reference to this object for use in functions + self = this, + // Variables, permitted sides and styles init = false, registered = false, @@ -42,27 +52,42 @@ slidebars = function () { // Variables var elements = $(), amount = '0px, 0px', - duration = parseFloat( offCanvas[ id ].element.css( 'transitionDuration' ), 10 ) * 1000; + size = '0px', + duration = parseFloat( offCanvas[ id ].element.css( 'transitionDuration' )/*, 10*/ ) * 1000; // Elements to animate - if ( offCanvas[ id ].style === 'reveal' || offCanvas[ id ].style === 'push' || offCanvas[ id ].style === 'shift' ) { + if ( 'reveal' === offCanvas[ id ].style || 'push' === offCanvas[ id ].style || 'shift' === offCanvas[ id ].style ) { elements = elements.add( canvas ); } - if ( offCanvas[ id ].style === 'push' || offCanvas[ id ].style === 'overlay' || offCanvas[ id ].style === 'shift' ) { + // @todo, fix reveal support for top and bottom + if ( 'reveal' === offCanvas[ id ].style && ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) ) { + elements = elements.add( offCanvas[ id ].element ); + } + + if ( 'push' === offCanvas[ id ].style || 'overlay' === offCanvas[ id ].style || 'shift' === offCanvas[ id ].style ) { elements = elements.add( offCanvas[ id ].element ); } // Amount to animate - if ( offCanvas[ id ].active ) { - if ( offCanvas[ id ].side === 'top' ) { - amount = '0px, ' + offCanvas[ id ].element.css( 'height' ); - } else if ( offCanvas[ id ].side === 'right' ) { - amount = '-' + offCanvas[ id ].element.css( 'width' ) + ', 0px'; - } else if ( offCanvas[ id ].side === 'bottom' ) { - amount = '0px, -' + offCanvas[ id ].element.css( 'height' ); - } else if ( offCanvas[ id ].side === 'left' ) { - amount = offCanvas[ id ].element.css( 'width' ) + ', 0px'; + if ( offCanvas[ id ].active || self.legacy ) { + if ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { + size = offCanvas[ id ].element.css( 'height' ); + } else { + size = offCanvas[ id ].element.css( 'width' ); + } + if ( self.legacy ) { + amount = size; + } else { + if ( 'top' === offCanvas[ id ].side ) { + amount = '0px, ' + size; + } else if ( 'right' === offCanvas[ id ].side ) { + amount = '-' + size + ', 0px'; + } else if ( 'bottom' === offCanvas[ id ].side ) { + amount = '0px, -' + size; + } else if ( 'left' === offCanvas[ id ].side ) { + amount = size + ', 0px'; + } } } @@ -92,17 +117,15 @@ slidebars = function () { isRegisteredSlidebar = function ( id ) { // Return if Slidebar is registered - if ( offCanvas.hasOwnProperty( id ) ) { - return true; - } else { - return false; - } + return ( offCanvas.hasOwnProperty( id ) ); }; /** * Initialization */ + this.legacy = false; + this.init = function ( callback ) { // Check if Slidebars has been initialized if ( init ) { @@ -116,8 +139,8 @@ slidebars = function () { var parameters = $( this ).attr( 'off-canvas' ).split( ' ', 3 ); // Make sure a valid id, side and style are specified - if ( ! parameters || ! parameters[ 0 ] || sides.indexOf( parameters[ 1 ] ) === -1 || styles.indexOf( parameters[ 2 ] ) === -1 ) { - throw "Error registering Slidebar, please specifiy a valid id, side and style'."; + if ( ! parameters || ! parameters[ 0 ] || -1 === sides.indexOf( parameters[ 1 ] ) || -1 === styles.indexOf( parameters[ 2 ] ) ) { + throw "Error registering Slidebar, please specify a valid id, side and style'."; } // Register Slidebar @@ -138,7 +161,7 @@ slidebars = function () { $( events ).trigger( 'init' ); // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } }; @@ -158,7 +181,7 @@ slidebars = function () { $( events ).trigger( 'exit' ); // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } }; @@ -184,19 +207,41 @@ slidebars = function () { // Loop through Slidebars to set negative margins for ( var id in offCanvas ) { // Check if Slidebar is registered - if ( isRegisteredSlidebar( id ) ) { + if ( offCanvas.hasOwnProperty( id ) && isRegisteredSlidebar( id ) ) { // Calculate offset var offset; - if ( offCanvas[ id ].side === 'top' || offCanvas[ id ].side === 'bottom' ) { + if ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { offset = offCanvas[ id ].element.css( 'height' ); } else { offset = offCanvas[ id ].element.css( 'width' ); } // Apply negative margins - if ( offCanvas[ id ].style === 'push' || offCanvas[ id ].style === 'overlay' || offCanvas[ id ].style === 'shift' ) { + var do_offset = false; + if ( 'push' === offCanvas[ id ].style || 'overlay' === offCanvas[ id ].style || 'shift' === offCanvas[ id ].style ) { + do_offset = true; + } else if ( 'reveal' === offCanvas[ id ].style && ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) ) { + // temp disabled style condition to enable reveal location as well for top and bottom + // @todo, fix reveal support for top and bottom, current result is behaviour similar to push + do_offset = true; + } + if ( do_offset ) { offCanvas[ id ].element.css( 'margin-' + offCanvas[ id ].side, '-' + offset ); + + // Fix shift style locations for legacy mode (1.9 to fix minor px rendering issues) + if ( self.legacy && 'shift' === offCanvas[ id ].style ) { + var shiftPos; + if ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { + shiftPos = offCanvas[ id ].element.height() / 1.9; + } else if ( 'left' === offCanvas[ id ].side || 'right' === offCanvas[ id ].side ) { + shiftPos = offCanvas[ id ].element.width() / 1.9; + } + // @todo, fix shift support for top and bottom + if ( 'left' === offCanvas[ id ].side || 'right' === offCanvas[ id ].side ) { + offCanvas[ id ].element.css( offCanvas[ id ].side, shiftPos + 'px' ); + } + } } } } @@ -210,7 +255,7 @@ slidebars = function () { $( events ).trigger( 'css' ); // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } }; @@ -245,10 +290,46 @@ slidebars = function () { var animationProperties = getAnimationProperties( id ); // Apply css - animationProperties.elements.css( { - 'transition-duration': animationProperties.duration + 'ms', - 'transform': 'translate(' + animationProperties.amount + ')' - } ); + var css = { + '-webkit-transition-duration': animationProperties.duration + 'ms', + '-moz-transition-duration': animationProperties.duration + 'ms', + '-o-transition-duration': animationProperties.duration + 'ms', + 'transition-duration': animationProperties.duration + 'ms' + }; + + if ( self.legacy ) { + css[ offCanvas[ id ].side ] = animationProperties.amount; + + var canvasSide; + if ( 'right' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { + // Bottom and Right animation for slidebars and the container are not the same + if ( 'right' === offCanvas[ id ].side ) { + canvasSide = 'left'; + } else if ( 'bottom' === offCanvas[ id ].side ) { + canvasSide = 'top'; + } + var canvasCss = { + '-webkit-transition-duration': animationProperties.duration + 'ms', + '-moz-transition-duration': animationProperties.duration + 'ms', + '-o-transition-duration': animationProperties.duration + 'ms', + 'transition-duration': animationProperties.duration + 'ms' + }; + canvasCss[ canvasSide ] = '-' + animationProperties.amount; + // Move container + if ( 'overlay' !== offCanvas[ id ].style ) { + canvas.css( canvasCss ); + } + // Open slidebar + animationProperties.elements.not( canvas ).css( css ); + } else { + // Top and Left sides can use the same css as all other elements. + animationProperties.elements.css( css ); + } + + } else { + css.transform = 'translate(' + animationProperties.amount + ')'; + animationProperties.elements.css( css ); + } // Transition completed setTimeout( function () { @@ -256,7 +337,7 @@ slidebars = function () { $( events ).trigger( 'opened', [ offCanvas[ id ].id ] ); // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } }, animationProperties.duration ); @@ -272,7 +353,7 @@ slidebars = function () { this.close = function ( id, callback ) { // Shift callback arguments - if ( typeof id === 'function' ) { + if ( 'function' === typeof id ) { callback = id; id = null; } @@ -304,12 +385,54 @@ slidebars = function () { var animationProperties = getAnimationProperties( id ); // Apply css - animationProperties.elements.css( 'transform', '' ); + if ( self.legacy ) { + var css = {}; + + var canvasSide; + if ( 'right' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { + // Bottom and Right animation for slidebars and the container are not the same + if ( 'right' === offCanvas[ id ].side ) { + canvasSide = 'left'; + } else if ( 'bottom' === offCanvas[ id ].side ) { + canvasSide = 'top'; + } + // Reset container + canvas.css( canvasSide, '' ); + + // Close slidebar + animationProperties.elements.not( canvas ).css( offCanvas[ id ].side, '' ); + } else { + // Top and Left sides can use the same css as all other elements. + animationProperties.elements.css( offCanvas[ id ].side, '' ); + } + + // Fix shift style for legacy mode (1.9 to fix minor px rendering issues) + if ( 'shift' === offCanvas[ id ].style ) { + var shiftPos; + if ( 'top' === offCanvas[ id ].side || 'bottom' === offCanvas[ id ].side ) { + shiftPos = offCanvas[ id ].element.height() / 1.9; + } else if ( 'left' === offCanvas[ id ].side || 'right' === offCanvas[ id ].side ) { + shiftPos = offCanvas[ id ].element.width() / 1.9; + } + // @todo, fix shift support for top and bottom + if ( 'left' === offCanvas[ id ].side || 'right' === offCanvas[ id ].side ) { + offCanvas[ id ].element.css( offCanvas[ id ].side, shiftPos + 'px' ); + } + } + + } else { + animationProperties.elements.css( 'transform', '' ); + } // Transition completetion setTimeout( function () { // Remove transition duration - animationProperties.elements.css( 'transition-duration', '' ); + animationProperties.elements.css( { + '-webkit-transition-duration': '', + '-moz-transition-duration': '', + '-o-transition-duration': '', + 'transition-duration': '' + } ); // Hide the Slidebar offCanvas[ id ].element.css( 'display', '' ); @@ -318,7 +441,7 @@ slidebars = function () { $( events ).trigger( 'closed', [ offCanvas[ id ].id ] ); // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } }, animationProperties.duration ); @@ -341,7 +464,7 @@ slidebars = function () { // It's open, close it this.close( id, function () { // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } } ); @@ -349,7 +472,7 @@ slidebars = function () { // It's closed, open it this.open( id, function () { // Run callback - if ( typeof callback === 'function' ) { + if ( 'function' === typeof callback ) { callback(); } } ); diff --git a/slidebars/slidebars.min.css b/slidebars/slidebars.min.css index 86896d1..b2f7dea 100644 --- a/slidebars/slidebars.min.css +++ b/slidebars/slidebars.min.css @@ -6,6 +6,10 @@ * Author url: http://www.adchsm.com/ * License: MIT * License url: http://www.adchsm.com/slidebars/license/ + * + * Modified by: Jory Hogeveen + * Version numbers below are related to Off-Canvas Sidebars, not Slidebars. + * + * @since 0.4 Enhance location selectors, added quotes. */ - -[canvas],[off-canvas*=push]{z-index:1}[off-canvas*=reveal],[off-canvas*=shift]{z-index:0}[canvas=container],[off-canvas],body,html{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body,html{width:100%;height:100%;overflow:hidden}[canvas=container]{width:100%;height:100%;overflow-y:auto;position:relative;background-color:#fff;-webkit-overflow-scrolling:touch}[canvas=container]:after,[canvas=container]:before{clear:both;content:'';display:table}[off-canvas]{display:none;position:fixed;overflow:hidden;overflow-y:auto;background-color:#000;color:#fff;-webkit-overflow-scrolling:touch}[off-canvas*=top]{width:100%;height:255px;top:0}[off-canvas*=right]{width:255px;height:100%;top:0;right:0}[off-canvas*=bottom]{width:100%;height:255px;bottom:0}[off-canvas*=left]{width:255px;height:100%;top:0;left:0}[off-canvas*=overlay]{z-index:9999}[canvas],[off-canvas]{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);-webkit-transition:-webkit-transform .3s;transition:transform .3s;-webkit-backface-visibility:hidden}[off-canvas*=shift][off-canvas*=top]{-webkit-transform:translate(0,50%);transform:translate(0,50%)}[off-canvas*=shift][off-canvas*=right]{-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}[off-canvas*=shift][off-canvas*=bottom]{-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}[off-canvas*=shift][off-canvas*=left]{-webkit-transform:translate(50%,0);transform:translate(50%,0)}@media print{[canvas]{-webkit-transform:translate(0,0)!important;-ms-transform:translate(0,0)!important;transform:translate(0,0)!important}[off-canvas]{display:none!important}} \ No newline at end of file +html,body,[canvas=container],[off-canvas]{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{width:100%;height:100%;overflow:hidden}[canvas]{z-index:1}[canvas=container]{width:100%;height:100%;overflow-y:auto;position:relative;background-color:white;-webkit-overflow-scrolling:touch}[canvas=container]:before,[canvas=container]:after{clear:both;content:'';display:table}[off-canvas]{display:none;position:fixed;overflow:hidden;overflow-y:auto;background-color:black;color:white;-webkit-overflow-scrolling:touch}[off-canvas*=" top"]{width:100%;height:255px;top:0}[off-canvas*=" right"]{width:255px;height:100%;top:0;right:0}[off-canvas*=" bottom"]{width:100%;height:255px;bottom:0}[off-canvas*=" left"]{width:255px;height:100%;top:0;left:0}[off-canvas*=" reveal"]{z-index:0}[off-canvas*=" push"]{z-index:1}[off-canvas*=" overlay"]{z-index:9999}[off-canvas*=" shift"]{z-index:0}[canvas],[off-canvas]{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);-webkit-transition:-webkit-transform 300ms;transition:transform 300ms;-webkit-backface-visibility:hidden}[off-canvas*=" shift"][off-canvas*=" top"]{-webkit-transform:translate(0,50%);transform:translate(0,50%)}[off-canvas*=" shift"][off-canvas*=" right"]{-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}[off-canvas*=" shift"][off-canvas*=" bottom"]{-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}[off-canvas*=" shift"][off-canvas*=" left"]{-webkit-transform:translate(50%,0);transform:translate(50%,0)}@media print{[canvas]{-webkit-transform:translate(0,0) !important;-ms-transform:translate(0,0) !important;transform:translate(0,0) !important}[off-canvas]{display:none !important}} \ No newline at end of file diff --git a/slidebars/slidebars.min.js b/slidebars/slidebars.min.js index 37f000d..1ed3c2b 100644 --- a/slidebars/slidebars.min.js +++ b/slidebars/slidebars.min.js @@ -1,4 +1,4 @@ -;/*! +;/** * Slidebars - A jQuery Framework for Off-Canvas Menus and Sidebars * Version: 2.0.2 * Url: http://www.adchsm.com/slidebars/ @@ -6,10 +6,16 @@ * Author url: http://www.adchsm.com/ * License: MIT * License url: http://www.adchsm.com/slidebars/license/ - */ - -/*! + * * Modified by: Jory Hogeveen + * Version numbers and info below is related to Off-Canvas Sidebars, not Slidebars. + * + * @package off-canvas-slidebars + * @author Jory Hogeveen + * + * @version 0.4 + * @since 0.4 Add scope for this reference + Add legacy CSS support (no hardware acceleration) + * @global slidebars + * @preserve */ - -var slidebars;!function($){slidebars=function(){var t=$("[canvas]"),e={},i=!1,n=!1,s=["top","right","bottom","left"],r=["reveal","push","overlay","shift"],o=function(i){var n=$(),s="0px, 0px",r=1e3*parseFloat(e[i].element.css("transitionDuration"),10);return("reveal"===e[i].style||"push"===e[i].style||"shift"===e[i].style)&&(n=n.add(t)),("push"===e[i].style||"overlay"===e[i].style||"shift"===e[i].style)&&(n=n.add(e[i].element)),e[i].active&&("top"===e[i].side?s="0px, "+e[i].element.css("height"):"right"===e[i].side?s="-"+e[i].element.css("width")+", 0px":"bottom"===e[i].side?s="0px, -"+e[i].element.css("height"):"left"===e[i].side&&(s=e[i].element.css("width")+", 0px")),{elements:n,amount:s,duration:r}},c=function(t,i,n,s){return a(t)?!1:void(e[t]={id:t,side:i,style:n,element:s,active:!1})},a=function(t){return e.hasOwnProperty(t)?!0:!1};this.init=function(t){return i?!1:(n||($("[off-canvas]").each(function(){var t=$(this).attr("off-canvas").split(" ",3);return t&&t[0]&&-1!==s.indexOf(t[1])&&-1!==r.indexOf(t[2])?void c(t[0],t[1],t[2],$(this)):!1}),n=!0),i=!0,this.css(),$(f).trigger("init"),void("function"==typeof t&&t()))},this.exit=function(t){if(!i)return!1;var e=function(){i=!1,$(f).trigger("exit"),"function"==typeof t&&t()};this.getActiveSlidebar()?this.close(e):e()},this.css=function(t){if(!i)return!1;for(var n in e)if(a(n)){var s;s="top"===e[n].side||"bottom"===e[n].side?e[n].element.css("height"):e[n].element.css("width"),("push"===e[n].style||"overlay"===e[n].style||"shift"===e[n].style)&&e[n].element.css("margin-"+e[n].side,"-"+s)}this.getActiveSlidebar()&&this.open(this.getActiveSlidebar()),$(f).trigger("css"),"function"==typeof t&&t()},this.open=function(t,n){if(!i)return!1;if(!t||!a(t))return!1;var s=function(){e[t].active=!0,e[t].element.css("display","block"),$(f).trigger("opening",[e[t].id]);var i=o(t);i.elements.css({"transition-duration":i.duration+"ms",transform:"translate("+i.amount+")"}),setTimeout(function(){$(f).trigger("opened",[e[t].id]),"function"==typeof n&&n()},i.duration)};this.getActiveSlidebar()&&this.getActiveSlidebar()!==t?this.close(s):s()},this.close=function(t,n){if("function"==typeof t&&(n=t,t=null),!i)return!1;if(t&&!a(t))return!1;if(t||(t=this.getActiveSlidebar()),t&&e[t].active){e[t].active=!1,$(f).trigger("closing",[e[t].id]);var s=o(t);s.elements.css("transform",""),setTimeout(function(){s.elements.css("transition-duration",""),e[t].element.css("display",""),$(f).trigger("closed",[e[t].id]),"function"==typeof n&&n()},s.duration)}},this.toggle=function(t,n){return i&&t&&a(t)?void(e[t].active?this.close(t,function(){"function"==typeof n&&n()}):this.open(t,function(){"function"==typeof n&&n()})):!1},this.isActive=function(){return i},this.isActiveSlidebar=function(t){return i&&t&&a(t)?e[t].active:!1},this.getActiveSlidebar=function(){if(!i)return!1;var t=!1;for(var n in e)if(a(n)&&e[n].active){t=e[n].id;break}return t},this.getSlidebars=function(){if(!i)return!1;var t=[];for(var n in e)a(n)&&t.push(e[n].id);return t},this.getSlidebar=function(t){return i&&t&&t&&a(t)?e[t]:!1},this.events={};var f=this.events;$(window).on("resize",this.css.bind(this))};}(jQuery); \ No newline at end of file +var slidebars;(function($){slidebars=function(){var canvas=$("[canvas]"),canvas_fixed=$("[canvas-fixed]");offCanvas={},self=this,init=false,registered=false,sides=["top","right","bottom","left"],styles=["reveal","push","overlay","shift"],getAnimationProperties=function(id){var elements=$(),amount="0px, 0px",size="0px",duration=parseFloat(offCanvas[id].element.css("transitionDuration"))*1e3;if("reveal"===offCanvas[id].style||"push"===offCanvas[id].style||"shift"===offCanvas[id].style){elements=elements.add(canvas)}if("reveal"===offCanvas[id].style&&("top"===offCanvas[id].side||"bottom"===offCanvas[id].side)){elements=elements.add(offCanvas[id].element)}if("push"===offCanvas[id].style||"overlay"===offCanvas[id].style||"shift"===offCanvas[id].style){elements=elements.add(offCanvas[id].element)}if(offCanvas[id].active||self.legacy){if("top"===offCanvas[id].side||"bottom"===offCanvas[id].side){size=offCanvas[id].element.css("height")}else{size=offCanvas[id].element.css("width")}if(self.legacy){amount=size}else{if("top"===offCanvas[id].side){amount="0px, "+size}else if("right"===offCanvas[id].side){amount="-"+size+", 0px"}else if("bottom"===offCanvas[id].side){amount="0px, -"+size}else if("left"===offCanvas[id].side){amount=size+", 0px"}}}return{elements:elements,amount:amount,duration:duration}},registerSlidebar=function(id,side,style,element){if(isRegisteredSlidebar(id)){throw"Error registering Slidebar, a Slidebar with id '"+id+"' already exists."}offCanvas[id]={id:id,side:side,style:style,element:element,active:false}},isRegisteredSlidebar=function(id){return offCanvas.hasOwnProperty(id)};this.legacy=false;this.init=function(callback){if(init){throw"Slidebars has already been initialized."}if(!registered){$("[off-canvas]").each(function(){var parameters=$(this).attr("off-canvas").split(" ",3);if(!parameters||!parameters[0]||-1===sides.indexOf(parameters[1])||-1===styles.indexOf(parameters[2])){throw"Error registering Slidebar, please specify a valid id, side and style'."}registerSlidebar(parameters[0],parameters[1],parameters[2],$(this))});registered=true}init=true;this.css();$(events).trigger("init");if("function"===typeof callback){callback()}};this.exit=function(callback){if(!init){throw"Slidebars hasn't been initialized."}var exit=function(){init=false;$(events).trigger("exit");if("function"===typeof callback){callback()}};if(this.getActiveSlidebar()){this.close(exit)}else{exit()}};this.css=function(callback){if(!init){throw"Slidebars hasn't been initialized."}for(var id in offCanvas){if(offCanvas.hasOwnProperty(id)&&isRegisteredSlidebar(id)){var offset;if("top"===offCanvas[id].side||"bottom"===offCanvas[id].side){offset=offCanvas[id].element.css("height")}else{offset=offCanvas[id].element.css("width")}var do_offset=false;if("push"===offCanvas[id].style||"overlay"===offCanvas[id].style||"shift"===offCanvas[id].style){do_offset=true}else if("reveal"===offCanvas[id].style&&("top"===offCanvas[id].side||"bottom"===offCanvas[id].side)){do_offset=true}if(do_offset){offCanvas[id].element.css("margin-"+offCanvas[id].side,"-"+offset);if(self.legacy&&"shift"===offCanvas[id].style){var shiftPos;if("top"===offCanvas[id].side||"bottom"===offCanvas[id].side){shiftPos=offCanvas[id].element.height()/1.9}else if("left"===offCanvas[id].side||"right"===offCanvas[id].side){shiftPos=offCanvas[id].element.width()/1.9}if("left"===offCanvas[id].side||"right"===offCanvas[id].side){offCanvas[id].element.css(offCanvas[id].side,shiftPos+"px")}}}}}if(this.getActiveSlidebar()){this.open(this.getActiveSlidebar())}$(events).trigger("css");if("function"===typeof callback){callback()}};this.open=function(id,callback){if(!init){throw"Slidebars hasn't been initialized."}if(!id||!isRegisteredSlidebar(id)){throw"Error opening Slidebar, there is no Slidebar with id '"+id+"'."}var open=function(){offCanvas[id].active=true;offCanvas[id].element.css("display","block");$(events).trigger("opening",[offCanvas[id].id]);var animationProperties=getAnimationProperties(id);var css={"-webkit-transition-duration":animationProperties.duration+"ms","-moz-transition-duration":animationProperties.duration+"ms","-o-transition-duration":animationProperties.duration+"ms","transition-duration":animationProperties.duration+"ms"};if(self.legacy){css[offCanvas[id].side]=animationProperties.amount;var canvasSide;if("right"===offCanvas[id].side||"bottom"===offCanvas[id].side){if("right"===offCanvas[id].side){canvasSide="left"}else if("bottom"===offCanvas[id].side){canvasSide="top"}var canvasCss={"-webkit-transition-duration":animationProperties.duration+"ms","-moz-transition-duration":animationProperties.duration+"ms","-o-transition-duration":animationProperties.duration+"ms","transition-duration":animationProperties.duration+"ms"};canvasCss[canvasSide]="-"+animationProperties.amount;if("overlay"!==offCanvas[id].style){canvas.css(canvasCss)}animationProperties.elements.not(canvas).css(css)}else{animationProperties.elements.css(css)}}else{css.transform="translate("+animationProperties.amount+")";animationProperties.elements.css(css)}setTimeout(function(){$(events).trigger("opened",[offCanvas[id].id]);if("function"===typeof callback){callback()}},animationProperties.duration)};if(this.getActiveSlidebar()&&this.getActiveSlidebar()!==id){this.close(open)}else{open()}};this.close=function(id,callback){if("function"===typeof id){callback=id;id=null}if(!init){throw"Slidebars hasn't been initialized."}if(id&&!isRegisteredSlidebar(id)){throw"Error closing Slidebar, there is no Slidebar with id '"+id+"'."}if(!id){id=this.getActiveSlidebar()}if(id&&offCanvas[id].active){offCanvas[id].active=false;$(events).trigger("closing",[offCanvas[id].id]);var animationProperties=getAnimationProperties(id);if(self.legacy){var css={};var canvasSide;if("right"===offCanvas[id].side||"bottom"===offCanvas[id].side){if("right"===offCanvas[id].side){canvasSide="left"}else if("bottom"===offCanvas[id].side){canvasSide="top"}canvas.css(canvasSide,"");animationProperties.elements.not(canvas).css(offCanvas[id].side,"")}else{animationProperties.elements.css(offCanvas[id].side,"")}if("shift"===offCanvas[id].style){var shiftPos;if("top"===offCanvas[id].side||"bottom"===offCanvas[id].side){shiftPos=offCanvas[id].element.height()/1.9}else if("left"===offCanvas[id].side||"right"===offCanvas[id].side){shiftPos=offCanvas[id].element.width()/1.9}if("left"===offCanvas[id].side||"right"===offCanvas[id].side){offCanvas[id].element.css(offCanvas[id].side,shiftPos+"px")}}}else{animationProperties.elements.css("transform","")}setTimeout(function(){animationProperties.elements.css({"-webkit-transition-duration":"","-moz-transition-duration":"","-o-transition-duration":"","transition-duration":""});offCanvas[id].element.css("display","");$(events).trigger("closed",[offCanvas[id].id]);if("function"===typeof callback){callback()}},animationProperties.duration)}};this.toggle=function(id,callback){if(!init){throw"Slidebars hasn't been initialized."}if(!id||!isRegisteredSlidebar(id)){throw"Error toggling Slidebar, there is no Slidebar with id '"+id+"'."}if(offCanvas[id].active){this.close(id,function(){if("function"===typeof callback){callback()}})}else{this.open(id,function(){if("function"===typeof callback){callback()}})}};this.isActive=function(id){return init};this.isActiveSlidebar=function(id){if(!init){throw"Slidebars hasn't been initialized."}if(!id){throw"You must provide a Slidebar id."}if(!isRegisteredSlidebar(id)){throw"Error retrieving Slidebar, there is no Slidebar with id '"+id+"'."}return offCanvas[id].active};this.getActiveSlidebar=function(){if(!init){throw"Slidebars hasn't been initialized."}var active=false;for(var id in offCanvas){if(isRegisteredSlidebar(id)){if(offCanvas[id].active){active=offCanvas[id].id;break}}}return active};this.getSlidebars=function(){if(!init){throw"Slidebars hasn't been initialized."}var slidebarsArray=[];for(var id in offCanvas){if(isRegisteredSlidebar(id)){slidebarsArray.push(offCanvas[id].id)}}return slidebarsArray};this.getSlidebar=function(id){if(!init){throw"Slidebars hasn't been initialized."}if(!id){throw"You must pass a Slidebar id."}if(!id||!isRegisteredSlidebar(id)){throw"Error retrieving Slidebar, there is no Slidebar with id '"+id+"'."}return offCanvas[id]};this.events={};var events=this.events;$(window).on("resize",this.css.bind(this))}})(jQuery); \ No newline at end of file diff --git a/uninstall.php b/uninstall.php index 1351575..3bb4efa 100644 --- a/uninstall.php +++ b/uninstall.php @@ -5,21 +5,21 @@ * Uninstall * @author Jory Hogeveen * @package off-canvas-sidebars - * @version 0.3 + * @version 0.4 * @todo Uninstall for multi-networks aswell */ //if uninstall not called from WordPress exit -if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) - exit(); - +if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { + die(); +} if ( ! is_multisite() ) { ocs_uninstall(); } else { global $wp_version; if ( version_compare( $wp_version, '4.5.999', '<' ) ) { - // Sadly does not work for large networks -> return false + // @codingStandardsIgnoreLine - Sadly does not work for large networks -> return false $blogs = wp_get_sites(); } else { $blogs = get_sites(); @@ -38,7 +38,7 @@ function ocs_uninstall( $blog_id = false ) { // Delete all options $option_keys = array( 'off_canvas_sidebars_options' ); if ( $blog_id ) { - if ( $blog_id == 'site' ) { + if ( 'site' === $blog_id ) { foreach ( $option_keys as $option_key ) { delete_site_option( $option_key ); } diff --git a/widgets/control-widget.php b/widgets/control-widget.php new file mode 100644 index 0000000..1d67364 --- /dev/null +++ b/widgets/control-widget.php @@ -0,0 +1,435 @@ + + * @package off-canvas-slidebars + * @version 0.4 + */ + +if ( ! defined( 'ABSPATH' ) ) { + die(); +} + +final class OCS_Off_Canvas_Sidebars_Control_Widget extends WP_Widget +{ + private $settings = array(); + private $general_labels = array(); + private $widget_setting = 'off-canvas-controls'; + + /** + * Sets up the widgets name etc + */ + public function __construct() { + parent::__construct( + 'Off-Canvas-Control', + __( 'Off-Canvas Control', 'off-canvas-sidebars' ), + array( + 'classname' => 'off_canvas_control', + 'description' => __( 'Button to trigger off-canvas sidebars', 'off-canvas-sidebars' ), + ) + ); + $this->load_plugin_data(); + } + + /** + * Get plugin defaults. + */ + function load_plugin_data() { + $off_canvas_sidebars = off_canvas_sidebars(); + $this->settings = $off_canvas_sidebars->get_settings(); + $this->general_labels = $off_canvas_sidebars->get_general_labels(); + //$this->general_key = $off_canvas_sidebars->get_general_key(); + //$this->plugin_key = $off_canvas_sidebars->get_plugin_key(); + } + + /** + * Outputs the content of the widget. + * + * @param array $args + * @param array $instance + */ + public function widget( $args, $instance ) { + + $this->load_plugin_data(); + $instance = $this->merge_settings( $instance ); + $prefix = $this->settings['css_prefix']; + + echo $args['before_widget']; + + echo '
'; + + foreach ( $this->settings['sidebars'] as $sidebar_id => $sidebar_data ) { + if ( ! $sidebar_data['enable'] || ! $instance[ $this->widget_setting ][ $sidebar_id ]['enable'] ) { + continue; + } + $widget_data = $instance[ $this->widget_setting ][ $sidebar_id ]; + $classes = array( + $prefix . '-trigger', + $prefix . '-toggle', + $prefix . '-toggle-' . $sidebar_id, + ); + if ( $widget_data['button_class'] ) { + //$classes[] = $prefix . '-button'; + $classes[] = 'button'; + } + + echo '
'; + echo '
'; + if ( $widget_data['show_icon'] ) { + if ( $widget_data['icon'] ) { + if ( strpos( $widget_data['icon'], 'dashicons' ) !== false ) { + wp_enqueue_style( 'dashicons' ); + } + echo ''; + } else { + wp_enqueue_style( 'dashicons' ); + echo ''; + } + } + if ( $widget_data['show_label'] ) { + echo '' . $widget_data['label'] . ''; + } + echo '
'; + }; + + echo '
'; + + echo $args['after_widget']; + } + + /** + * Outputs the options form on admin. + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @todo Refactor to enable above checks? + * + * @param array $instance The widget options. + * @return void + */ + public function form( $instance ) { + $off_canvas_sidebars = off_canvas_sidebars(); + $this->load_plugin_data(); + $instance = $this->merge_settings( $instance ); + + $ocs = $instance[ $this->widget_setting ]; + $field_id = $this->get_field_id( $this->widget_setting ); + $field_name = $this->get_field_name( $this->widget_setting ); + ?> +

+ :
+ settings['sidebars'] as $sidebar_id => $value ) { + if ( empty( $this->settings['sidebars'][ $sidebar_id ]['enable'] ) ) { + continue; + } + ?> + + + + +

+ + is_sidebar_enabled() ) { + echo '

' . $this->general_labels['no_sidebars_available'] . '

'; + } else { + ?> + +
+ + + +
+ settings['sidebars'] as $sidebar_id => $value ) { + if ( empty( $this->settings['sidebars'][ $sidebar_id ]['enable'] ) ) { + continue; + } + $hidden = 'style="display:none;"'; + $field_sidebar_id = $field_id . '_' . $sidebar_id; + $field_sidebar_name = $field_name . '[' . $sidebar_id . ']'; + ?> +
> +

+

+ > + +

+

> + + +

+

+ > + +

+

> + + +

+

+ > + +

+
+
+ +
+ +

+ +

+ widget( array( 'before_widget' => '', 'after_widget' => '' ), $instance ); ?> +
+

+ + + + load_plugin_data(); + $instance = $this->merge_settings( $instance ); + + $ocs = $instance[ $this->widget_setting ]; + $new_ocs = array(); + if ( ! empty( $new_instance[ $this->widget_setting ] ) ) { + $new_ocs = $new_instance[ $this->widget_setting ]; + } + + // checkboxes + foreach ( $new_ocs as $sidebar_id => $value ) { + $new_ocs[ $sidebar_id ]['enable'] = ( ! empty( $new_ocs[ $sidebar_id ]['enable'] ) ) ? 1 : 0; + $new_ocs[ $sidebar_id ]['show_label'] = ( ! empty( $new_ocs[ $sidebar_id ]['show_label'] ) ) ? 1 : 0; + $new_ocs[ $sidebar_id ]['show_icon'] = ( ! empty( $new_ocs[ $sidebar_id ]['show_icon'] ) ) ? 1 : 0; + $new_ocs[ $sidebar_id ]['button_class'] = ( ! empty( $new_ocs[ $sidebar_id ]['button_class'] ) ) ? 1 : 0; + } + + $new_ocs = array_map( array( $this, 'sanitize_value' ), $new_ocs ); + + foreach ( $new_ocs as $sidebar_id => $sidebar_settings ) { + if ( empty( $ocs[ $sidebar_id ] ) ) { + $ocs[ $sidebar_id ] = $sidebar_settings; + continue; + } + if ( is_array( $sidebar_settings ) ) { + foreach ( $new_ocs[ $sidebar_id ] as $setting => $value ) { + $ocs[ $sidebar_id ][ $setting ] = $value; + } + } else { + $ocs[ $sidebar_id ] = $sidebar_settings; + } + } + + $instance[ $this->widget_setting ] = $ocs; + + return $instance; + } + + /** + * Merge instance with defaults + * + * @param array $settings + * @return array $settings + */ + function merge_settings( $settings ) { + $defaults = array(); + + foreach ( $this->settings['sidebars'] as $key => $value ) { + $defaults[ $key ] = array( + 'enable' => 0, + 'show_label' => 0, + 'label' => 'menu', + 'show_icon' => 1, + 'icon' => false, + 'button_class' => 1, + ); + }; + + $ocs = array(); + if ( ! empty( $settings[ $this->widget_setting ] ) ) { + $ocs = $settings[ $this->widget_setting ]; + } + + foreach ( $defaults as $key => $value ) { + if ( empty( $ocs[ $key ] ) ) { + $ocs[ $key ] = $value; + continue; + } + foreach ( $defaults[ $key ] as $key2 => $value2 ) { + if ( ! isset( $ocs[ $key ][ $key2 ] ) ) { + $ocs[ $key ][ $key2 ] = $value2; + } + } + } + + $settings[ $this->widget_setting ] = $ocs; + + return $settings; + } + + /** + * Sanitize values. + * + * @param mixed $val The value + * @return mixed + */ + public function sanitize_value( $val ) { + if ( is_array( $val ) ) { + return array_map( array( $this, 'sanitize_value' ), $val ); + } elseif ( is_string( $val ) ) { + return strip_tags( stripslashes( $val ) ); + } elseif ( is_object( $val ) ) { + return null; + } + return $val; + } +} diff --git a/widgets/off-canvas-sidebars-widget.php b/widgets/off-canvas-sidebars-widget.php deleted file mode 100644 index 1be945e..0000000 --- a/widgets/off-canvas-sidebars-widget.php +++ /dev/null @@ -1,278 +0,0 @@ - - * @package off-canvas-slidebars - * @version 0.3 - */ - -! defined( 'ABSPATH' ) and die( 'You shall not pass!' ); - -final class OCS_Off_Canvas_Sidebars_Control_Widget extends WP_Widget -{ - private $general_settings = array(); - private $general_labels = array(); - private $widget_setting = 'off-canvas-controls'; - - /** - * Sets up the widgets name etc - */ - public function __construct() { - // widget actual processes - parent::__construct( - 'Off-Canvas-Control', - __('Off-Canvas Control', 'off-canvas-sidebars'), - array( - 'class_name' => 'off_canvas_control', - 'description' => __('Button to trigger off-canvas sidebars', 'off-canvas-sidebars' ), - ) - ); - - $this->load_plugin_data(); - } - - /** - * Get plugin defaults - */ - function load_plugin_data() { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $this->general_settings = $off_canvas_sidebars->get_settings(); - $this->general_labels = $off_canvas_sidebars->get_general_labels(); - //$this->general_key = $off_canvas_sidebars->get_general_key(); - //$this->plugin_key = $off_canvas_sidebars->get_plugin_key(); - } - - /** - * Outputs the content of the widget - * - * @param array $args - * @param array $instance - */ - public function widget( $args, $instance ) { - - $this->load_plugin_data(); - $instance = $this->merge_settings( $instance ); - $prefix = $this->general_settings['css_prefix']; - - // outputs the content of the widget - echo $args['before_widget'].'
'; - - ?> -
- general_settings['sidebars'] as $sidebar_id => $sidebar_data ) { - if ( $sidebar_data['enable'] == 1 && $instance[ $this->widget_setting ][ $sidebar_id ]['enable'] == 1 ) { - $widget_data = $instance[ $this->widget_setting ][ $sidebar_id ]; - $classes = array( - $prefix . '-button', - $prefix . '-toggle', - $prefix . '-toggle-' . $sidebar_id - ); - if ( $widget_data['button_class'] == 1 ) { - $classes[] = 'button'; - } - ?> -
-
- - - - - - - - - - - -
-
- -
- '.$args['after_widget']; - } - - /** - * Outputs the options form on admin - * - * @param array $instance The widget options - * @return void - */ - public function form( $instance ) { - $off_canvas_sidebars = Off_Canvas_Sidebars(); - $this->load_plugin_data(); - $instance = $this->merge_settings( $instance ); - ?> -

-   - general_settings['sidebars'] as $sidebar_id => $value ) { - if ( empty( $this->general_settings['sidebars'][ $sidebar_id ]['enable'] ) ) { - continue; - } - ?> -   - - -

- - is_sidebar_enabled() ) { - echo '

' . $this->general_labels['no_sidebars_available'] . '

'; - } else { - ?> - -
- - general_settings['sidebars'] as $sidebar_id => $value ) { - if ( empty( $this->general_settings['sidebars'][ $sidebar_id ]['enable'] ) ) { - continue; - } - $hidden = ''; - if ( empty( $instance[ $this->widget_setting ][ $sidebar_id ]['enable'] ) ) { - $hidden = 'style="display:none;"'; - } - ?> -
> -

-

- widget_setting ][ $sidebar_id ]['show_label'], 1 ); ?>> - -

-

widget_setting ][ $sidebar_id ]['show_label'] != 1)?'style="display: none;"':''; ?>> - - -

- widget_setting ][ $sidebar_id ]['show_icon'], 1 ); ?>> - -

-

widget_setting ][ $sidebar_id ]['show_icon'] != 1)?'style="display: none;"':''; ?>> - - -

-

- widget_setting ][ $sidebar_id ]['button_class'], 1 ); ?>> - -

-
-
- - -

- -

- widget( array( 'before_widget'=>'','after_widget'=>'' ), $instance ); ?> -
-

- - - - load_plugin_data(); - $instance = $this->merge_settings( $instance ); - - // checkboxes - foreach ( $instance[ $this->widget_setting ] as $sidebar_id => $value ) { - $instance[ $this->widget_setting ][ $sidebar_id ]['enable'] = ( ! empty( $new_instance[ $this->widget_setting ][ $sidebar_id ]['enable'] ) ) ? strip_tags( $new_instance[ $this->widget_setting ][ $sidebar_id ]['enable'] ) : '0'; - $instance[ $this->widget_setting ][ $sidebar_id ]['show_label'] = ( ! empty( $new_instance[ $this->widget_setting ][ $sidebar_id ]['show_label'] ) ) ? strip_tags( $new_instance[ $this->widget_setting ][ $sidebar_id ]['show_label'] ) : '0'; - $instance[ $this->widget_setting ][ $sidebar_id ]['show_icon'] = ( ! empty( $new_instance[ $this->widget_setting ][ $sidebar_id ]['show_icon'] ) ) ? strip_tags( $new_instance[ $this->widget_setting ][ $sidebar_id ]['show_icon'] ) : '0'; - $instance[ $this->widget_setting ][ $sidebar_id ]['button_class'] = ( ! empty( $new_instance[ $this->widget_setting ][ $sidebar_id ]['button_class'] ) ) ? strip_tags( $new_instance[ $this->widget_setting ][ $sidebar_id ]['button_class'] ) : '0'; - } - // Allow 3 level arrays - foreach ( $new_instance as $key => $value ) { - if ( is_array( $value ) ) { - foreach ( $new_instance[ $key ] as $key2 => $value2 ) { - if ( is_array( $value2 ) ) { - foreach ( $new_instance[ $key ][ $key2 ] as $key3 => $value3 ) { - $instance[ $key ][ $key2 ][ $key3 ] = strip_tags( stripslashes( $new_instance[ $key ][ $key2 ][ $key3 ] ) ); - } - } else { - $instance[ $key ][ $key2 ] = strip_tags( stripslashes( $new_instance[ $key ][ $key2 ] ) ); - } - } - } else { - $instance[ $key ] = strip_tags( stripslashes( $new_instance[ $key ] ) ); - } - } - return $instance; - } - - /** - * Merge instance with defaults - * - * @param array $args - * @return array $args - */ - function merge_settings( $args ) { - $defaults = array( - $this->widget_setting => array() - ); - - foreach ( $this->general_settings['sidebars'] as $key => $value ) { - $defaults[ $this->widget_setting ][ $key ] = array( - 'enable' => 0, - 'show_label' => 0, - 'label' => 'menu', - 'show_icon' => 1, - 'icon' => false, - 'button_class' => 1 - ); - }; - - $args = array_merge( $defaults, $args ); - - foreach ( $defaults[ $this->widget_setting ] as $key => $value ) { - if ( empty( $args[ $this->widget_setting ][ $key ] ) ) { - $args[ $this->widget_setting ][ $key ] = $defaults[ $this->widget_setting ][ $key ]; - } - foreach ( $defaults[ $this->widget_setting ][ $key ] as $key2 => $value2 ) { - if ( empty( $args[ $this->widget_setting ][ $key ][ $key2 ] ) ) { - $args[ $this->widget_setting ][ $key ][ $key2 ] = $defaults[ $this->widget_setting ][ $key ][ $key2 ]; - } - } - } - return $args; - } -}