diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5dfbb4c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/*
+node_modules/*
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..7c84238
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,50 @@
+module.exports = function(grunt) {
+
+ // Project configuration.
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+ copy: {
+ main: {
+ files: [
+ {expand: true, src: ['assets/**'], dest: 'build/'},
+ {expand: true, src: ['views/**'], dest: 'build/'},
+ {expand: true, src: ['walkers/**'], dest: 'build/'},
+ {expand: false, src: ['readme.txt'], dest: 'build/readme.txt'},
+ {expand: false, src: ['screenshot-1.png'], dest: 'build/screenshot-1.png'},
+ {expand: false, src: ['screenshot-2.png'], dest: 'build/screenshot-2.png'},
+ {expand: false, src: ['screenshot-3.png'], dest: 'build/screenshot-3.png'},
+ {expand: false, src: ['screenshot-4.png'], dest: 'build/screenshot-4.png'},
+ {expand: false, src: ['submenu.php'], dest: 'build/submenu.php'},
+ {expand: false, src: ['SubmenuAdmin.php'], dest: 'build/SubmenuAdmin.php'},
+ {expand: false, src: ['SubmenuModel.php'], dest: 'build/SubmenuModel.php'}
+ ]
+ }
+ },
+ clean: ["build"],
+ uglify: {
+ my_target: {
+ files: {
+ 'build/assets/js/ajax.js': ['assets/js/ajax.js'],
+ 'build/assets/js/main.js': ['assets/js/main.js']
+ }
+ }
+ },
+ cssmin: {
+ my_target: {
+ files: {
+ 'build/assets/css/admin.css': ['assets/css/admin.css']
+ }
+ }
+ }
+ });
+
+ // grunt modules
+ grunt.loadNpmTasks('grunt-contrib-copy');
+ grunt.loadNpmTasks('grunt-contrib-clean');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-contrib-cssmin');
+
+ // Default task(s).
+ grunt.registerTask('default', ['clean', 'copy', 'uglify', 'cssmin']);
+
+};
\ No newline at end of file
diff --git a/SubmenuAdmin.php b/SubmenuAdmin.php
new file mode 100644
index 0000000..f9e077c
--- /dev/null
+++ b/SubmenuAdmin.php
@@ -0,0 +1,230 @@
+
+ * @version 0.0.1
+ */
+class SubmenuAdmin{
+
+ /**
+ * Plugin config
+ * @var stdClass
+ */
+ private $config = null;
+
+ /**
+ * Setup class
+ * @param stdClass $config
+ * @return void
+ */
+ public function __construct(&$config){
+ $this->config = $config;
+
+ // include js/css
+ add_action( 'admin_enqueue_scripts', array($this, 'load_scripts'));
+
+ // on menu save
+ add_action( 'wp_update_nav_menu_item', array($this, 'save_nav_menu'), 10, 3);
+
+ add_action( 'admin_notices', array( $this , 'display_admin_notification' ) );
+ add_action( 'admin_init', array( $this, 'hide_admin_notification' ) );
+
+ // register admin settings
+ add_action( 'admin_init', array($this, 'register_settings' ));
+
+ // add settings page
+ add_action( 'admin_menu', array($this, 'settings_menu' ));
+
+ // load settings
+ $options = get_option( 'jcs-general_settings' );
+ $this->config->edit_walker = isset($options['enable_walker']) && $options['enable_walker'] == 1 ? 1 : 0;
+
+ if($this->config->edit_walker == 1){
+ add_filter( 'wp_edit_nav_menu_walker', array($this, 'set_edit_walker'));
+ }else{
+ add_action( 'wp_ajax_jcs_get_menu_item', array( $this, 'ajax_get_menu_item' ) );
+ }
+ }
+
+ /**
+ * Attach plugin assets
+ * @return void
+ */
+ public function load_scripts(){
+
+ // attach files
+ wp_enqueue_script('jc-submenu-scripts', $this->config->plugin_url .'/assets/js/main.js', array('jquery'), $this->config->version, true);
+ wp_enqueue_style('jc-submenu-admin-css', $this->config->plugin_url .'/assets/css/admin.css', array(), $this->config->version);
+
+ // ajax files
+ if($this->config->edit_walker == 0){
+ wp_enqueue_script( 'jc-submenu-ajax', $this->config->plugin_url .'/assets/js/ajax.js', array('jquery'), $this->config->version );
+ wp_localize_script( 'jc-submenu-ajax', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'we_value' => 1234 ) );
+ }
+ }
+
+ public function settings_menu(){
+ // add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function );
+ add_submenu_page( 'options-general.php', 'JC Submenu', 'JC Submenu', 'manage_options', 'jc-submenu', array($this, 'admin_settings_view') );
+ }
+
+ public function admin_settings_view(){
+ include $this->config->plugin_dir . 'views/settings.php';
+ }
+
+ /**
+ * Save custom menu item options
+ * @param int $menu_id
+ * @param int $menu_item_db_id
+ * @param array $args
+ * @return void
+ */
+ public function save_nav_menu($menu_id, $menu_item_db_id, $args){
+
+ if(!isset($_POST['menu-item-title']) || empty($_POST['menu-item-title']))
+ return false;
+
+ foreach($_POST['menu-item-title'] as $menu_item_id => $menu_item_title){
+
+ if(isset($_POST[$this->config->prefix.'-admin']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-admin'])){
+ SubmenuModel::save_meta($menu_item_id, 'admin', 1);
+ }elseif(isset($_POST[$this->config->prefix.'-active']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-active'])){
+ SubmenuModel::save_meta($menu_item_id, 'admin', 0);
+ }
+
+ if(isset($_POST[$this->config->prefix.'-autopop']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-autopop'])){
+ // save post meta for active items
+ SubmenuModel::save_menu_item($menu_item_id);
+
+ }elseif(isset($_POST[$this->config->prefix.'-active']) && array_key_exists($menu_item_id, $_POST[$this->config->prefix.'-active'])){
+ // clear post meta for inactive items
+ SubmenuModel::clear_menu_item($menu_item_id);
+ }
+ }
+ }
+
+ /**
+ * Output Usage Notification
+ * @return void
+ */
+ public function display_admin_notification(){
+
+ global $current_user;
+ global $pagenow;
+
+ $user_id = $current_user->ID;
+ $response = get_user_meta($user_id, 'jcs-show_notification', true);
+
+ if ( current_user_can( 'manage_options' ) && (!$response || $response < $this->config->version_check) && $pagenow == 'nav-menus.php'): ?>
+
+
+
+ ID;
+
+ if(isset($_GET['jc_hide_notice']) && $_GET['jc_hide_notice'] == 1){
+
+ delete_user_meta($user_id, 'jcs-show_notification');
+ add_user_meta( $user_id, 'jcs-show_notification', $this->config->version_check, true);
+ }
+
+ }
+
+ /**
+ * Change nav-menu.php walker
+ * @return string
+ */
+ public function set_edit_walker(){
+ return 'JC_Submenu_Admin_Walker';
+ }
+
+ /**
+ * Load menu admin edit view
+ * @return void
+ */
+ public function ajax_get_menu_item(){
+ $item_id = intval($_POST['id']);
+ include $this->config->plugin_dir . 'views/edit.php';
+ die();
+ }
+
+ public function register_settings(){
+
+ // Settings
+ register_setting('jcs_settings', 'jcs'. '-general_settings', array($this, 'save_settings'));
+
+ add_settings_section('settings', 'General Settings', array($this, 'section_settings'), 'tab_settings');
+
+ add_settings_field('enable_walker', 'Enable Admin Walker', array($this, 'field_callback'), 'tab_settings', 'settings', array(
+ 'type' => 'checkbox',
+ 'field_id' => 'enable_walker',
+ 'section_id' => 'settings',
+ 'setting_id' => 'jcs'. '-general_settings'
+ ));
+
+ }
+
+ /**
+ * Settings Section Text
+ *
+ * @return void
+ */
+ public function section_settings($section)
+ {
+ switch($section['id']){
+ case 'settings':
+ echo 'Enable Admin Walker, only do this if you are having problems with editing your menus.';
+ break;
+ }
+
+ }
+
+ /**
+ * Create Settings Fields
+ *
+ * @param array $args
+ * @return void
+ */
+ public function field_callback($args){
+ $multiple = false;
+ extract($args);
+ $options = get_option($setting_id);
+ switch($args['type'])
+ {
+ case 'checkbox':{
+ $checked = isset($options[$field_id]) && $options[$field_id] == 1 ? 'checked="checked"' : '';
+ ?>
+ />
+
+ * @version 0.0.1
+ */
+class SubmenuModel{
+
+ /**
+ * Plugin config
+ * @var stdClass
+ */
+ static $config;
+
+ /**
+ * Order by options
+ * @var array
+ */
+ private static $order_options = array(
+ 'tax' => array(
+ 'name' => 'Name',
+ 'slug' => ' Slug',
+ 'count' => 'Tax Count',
+ 'id' => 'ID',
+ 'none' => 'None',
+ ),
+ 'post' => array(
+ 'title' => 'Post Name',
+ 'name' => 'Post Slug',
+ 'none' => 'None',
+ 'ID' => 'ID',
+ 'date' => 'Date',
+ 'comment_count' => 'Total Comments',
+ 'menu_order' => 'Menu Order'
+ ),
+ 'page' => array(
+ 'post_title' => 'Page Name',
+ 'menu_order' => 'Menu Order',
+ 'post_date' => 'Created',
+ 'post_modified' => 'Last Modified',
+ 'ID' => 'Page ID',
+ 'post_author' => 'Author',
+ 'post_name' => 'Page Slug'
+ )
+ );
+
+ /**
+ * Setup class
+ * @param stdClass $config
+ * @return void
+ */
+ static function init(&$config){
+ self::$config = $config;
+ }
+
+ /**
+ * Save Menu item from wp admin navigation page
+ * @param int $menu_item_id
+ * @param array $args
+ * @return void
+ */
+ static function save_menu_item($menu_item_id = null, $args = array()){
+ $type = self::get_post_data($menu_item_id, 'populate-type');
+ $value = self::get_post_data($menu_item_id, 'populate-'.$type);
+
+ $childpop = self::get_post_data($menu_item_id, 'childpop');
+ $childpop = $childpop == 0 ? 0 : 1;
+
+ if($type && $value){
+
+ // validate population type
+ if(!in_array($type, array('post','tax', 'page', 'archive'))){
+ return 0;
+ }
+
+ if($type == 'post'){
+ $post_limit = self::get_post_data($menu_item_id, 'post-limit');
+ $post_order = self::get_post_data($menu_item_id, 'post-order');
+ $post_orderby = self::get_post_data($menu_item_id, 'post-orderby');
+ $post_tax = self::get_post_data($menu_item_id, 'post-tax');
+ $post_term = self::get_post_data($menu_item_id, 'post-term');
+
+ $post_tax = !empty($post_tax) ? $post_tax : 0;
+ $post_term = !empty($post_term) ? $post_term : 0;
+
+
+ $post_limit = intval($post_limit);
+
+ // validate order
+ if(!array_key_exists($post_orderby, self::get_order_options('post'))){
+ echo $post_orderby;
+ echo 'A';
+ return 0;
+ }
+ if(!in_array($post_order, array('ASC', 'DESC'))){
+ echo 'B';
+ return 0;
+ }
+
+ self::save_meta($menu_item_id, 'post-limit', $post_limit);
+ self::save_meta($menu_item_id, 'post-order', $post_order);
+ self::save_meta($menu_item_id, 'post-orderby', $post_orderby);
+ self::save_meta($menu_item_id, 'post-tax', $post_tax);
+ self::save_meta($menu_item_id, 'post-term', $post_term);
+ // self::save_post_tax($menu_item_id, $post_tax);
+ }elseif($type == 'tax'){
+ $tax_order = self::get_post_data($menu_item_id, 'tax-order');
+ $tax_orderby = self::get_post_data($menu_item_id, 'tax-orderby');
+ $tax_empty = self::get_post_data($menu_item_id, 'tax-empty');
+ $tax_depth = self::get_post_data($menu_item_id, 'tax-depth');
+ $tax_term = self::get_post_data($menu_item_id, 'tax-term');
+
+ $tax_term = !empty($tax_term) ? $tax_term : 0;
+
+ $tax_exclude = self::get_post_data($menu_item_id, 'tax-exclude');
+ if(!empty($tax_exclude)){
+
+ $temp = array();
+ $tax_exclude = explode(',', str_replace(' ', '', $tax_exclude));
+
+ foreach($tax_exclude as $id){
+ if(intval($id) > 0 && !in_array(intval($id), $temp)){
+ $temp[] = intval($id);
+ }
+ }
+ $tax_exclude = $temp;
+ }else{
+ $tax_exclude = array();
+ }
+
+
+ $tax_empty = $tax_empty == 1 ? 1 : 0;
+
+ // validate order
+ if(!array_key_exists($tax_orderby, self::get_order_options('tax'))){
+ return 0;
+ }
+ if(!in_array($tax_order, array('ASC', 'DESC'))){
+ return 0;
+ }
+
+ self::save_meta($menu_item_id, 'tax-order', $tax_order);
+ self::save_meta($menu_item_id, 'tax-orderby', $tax_orderby);
+ self::save_meta($menu_item_id, 'tax-empty', $tax_empty);
+ self::save_meta($menu_item_id, 'tax-depth', intval($tax_depth));
+ self::save_meta($menu_item_id, 'tax-exclude', $tax_exclude);
+ self::save_meta($menu_item_id, 'tax-term', $tax_term);
+ }elseif($type == 'page'){
+
+ $page_order = self::get_post_data($menu_item_id, 'page-order');
+ $page_orderby = self::get_post_data($menu_item_id, 'page-orderby');
+ $page_exclude = self::get_post_data($menu_item_id, 'page-exclude');
+
+ // validate order
+ if(!array_key_exists($page_orderby, self::get_order_options('page'))){
+ return 0;
+ }
+ if(!in_array($page_order, array('ASC', 'DESC'))){
+ return 0;
+ }
+
+ self::save_meta($menu_item_id, 'page-order', $page_order);
+ self::save_meta($menu_item_id, 'page-orderby', $page_orderby);
+ self::save_meta($menu_item_id, 'page-exclude', $page_exclude);
+ }elseif($type == 'archive'){
+
+ $archive_group = self::get_post_data($menu_item_id, 'archive-group');
+ $archive_group = $archive_group == 1 ? 1 : 0;
+ self::save_meta($menu_item_id, 'archive-group', $archive_group);
+ }
+
+ // all validated save rest
+ self::save_meta($menu_item_id, 'populate-type', $type);
+ self::save_meta($menu_item_id, 'populate-value', $value);
+ self::save_meta($menu_item_id, 'autopopulate', 1);
+ self::save_meta($menu_item_id, 'childpop', $childpop);
+ }
+
+ }
+
+ /**
+ * Save post type taxonomy filter
+ * @param $menu_item_id
+ * @param $string
+ */
+ static function save_post_tax($menu_item_id = 0, $string = ''){
+
+ // no string to parse
+ if(empty($string)){
+ self::save_meta($menu_item_id, 'post-tax', 0);
+ self::save_meta($menu_item_id, 'post-term', 0);
+ return false;
+ }
+
+
+ // save tax only
+ if(strpos($string, '-') === false && (taxonomy_exists( $string ) || $string == 0 ) ){
+ self::save_meta($menu_item_id, 'post-tax', $string);
+ self::save_meta($menu_item_id, 'post-term', 0);
+ return true;
+ }
+
+ // save term and tax
+ $split = explode('-', $string);
+
+ if(count($split) == 2){
+ $term_id = intval($split[1]);
+ $tax = $split[0];
+
+ if(taxonomy_exists( $tax ) && (get_term_by( 'id', $term_id, $tax) || $term_id == 0) ){
+ self::save_meta($menu_item_id, 'post-tax', $tax);
+ self::save_meta($menu_item_id, 'post-term', $term_id);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Capture menu item $_POST data
+ * @param $menu_item_id
+ * @param $key
+ */
+ static function get_post_data($menu_item_id = 0, $key = ''){
+ if(isset($_POST[self::$config->prefix.'-'.$key][$menu_item_id])
+ && !empty($_POST[self::$config->prefix.'-'.$key][$menu_item_id])){
+ return $_POST[self::$config->prefix.'-'.$key][$menu_item_id];
+ }else{
+ return '';
+ };
+ }
+
+ /**
+ * Update post meta data
+ * @param int $menu_item_id
+ * @param string $meta_key
+ * @param string $new_value
+ */
+ static function save_meta($menu_item_id = 0, $meta_key = '', $new_value = ''){
+
+ $key = self::$config->prefix.'-'.$meta_key;
+
+ $old_value = get_post_meta( $menu_item_id, $key, true );
+ if($old_value == ''){
+
+ // fix to remove multiple saved values as add_post_meta was not set to unique... woops
+ global $wpdb;
+ $wpdb->query( $wpdb->prepare( "DELETE pm FROM {$wpdb->prefix}postmeta as pm WHERE pm.post_id = %d AND meta_key=%s ", $menu_item_id , $key ) );
+
+ // add value
+ add_post_meta( $menu_item_id, $key, $new_value, true );
+ }else{
+ // update value
+ update_post_meta( $menu_item_id, $key, $new_value, $old_value );
+ }
+ }
+
+ /**
+ * Remove menu item settings
+ * @param int $menu_item_id
+ * @return void
+ */
+ static function clear_menu_item($menu_item_id = null){
+ $keys = array(
+ 'populate-type',
+ 'populate-value',
+ 'autopopulate',
+ 'post-limit',
+ 'post-order',
+ 'post-orderby',
+ 'tax-order',
+ 'tax-orderby',
+ 'tax-empty',
+ 'post-tax',
+ 'post-term',
+ 'childpop',
+ 'archive-group'
+ );
+
+ foreach($keys as $meta_key){
+ $old_value = get_post_meta( $menu_item_id, self::$config->prefix.'-'.$meta_key, true );
+ if($old_value != ''){
+ delete_post_meta( $menu_item_id, self::$config->prefix.'-'.$meta_key, $old_value );
+ }
+ }
+ }
+
+ /**
+ * Retrieve orderby options
+ * @param string $type tax | post
+ */
+ static function get_order_options($type){
+
+ switch($type){
+ case 'tax':
+ return self::$order_options['tax'];
+ break;
+ case 'post':
+ return self::$order_options['post'];
+ break;
+ case 'page':
+ return self::$order_options['page'];
+ break;
+ }
+ }
+
+ /**
+ * Get plugin meta item
+ * @param int $menu_item_id
+ * @param string $key
+ * @return string
+ */
+ static function get_meta($menu_item_id, $key){
+ return get_post_meta( $menu_item_id, self::$config->prefix.'-'.$key, true );
+ }
+}
+?>
\ No newline at end of file
diff --git a/assets/css/admin.css b/assets/css/admin.css
new file mode 100644
index 0000000..6d60238
--- /dev/null
+++ b/assets/css/admin.css
@@ -0,0 +1,79 @@
+.jc-submenu-populate-block{
+ color: #777;
+ border: #DFDFDF 1px solid;
+ /*border-bottom: none;*/
+ /*padding: 10px 0 10px 10px;*/
+ padding:0;
+ width: 367px;
+}
+
+.jc-submenu-populate-block label{
+ display: block;
+}
+
+.jc-submenu-populate-block input[type=text], .jc-submenu-populate-block select{
+ width:100%;
+}
+
+.jc-submenu-row{
+ clear: both;
+ margin:10px 0 10px 10px;
+}
+
+.jc-submenu-row p{
+ padding-right: 4%;
+ width:96%;
+ margin-bottom: 5px;
+ margin-top: 5px;
+}
+
+.jc-submenu-row .jc_two_cols{
+ overflow: hidden;
+}
+
+.jc-submenu-row.jc_two_cols p{
+ width:46%;
+ float:left;
+ padding-right:4%;
+}
+
+.jc-accord-heading input{
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+}
+p.jc-accord-heading{
+ margin: 0;
+ padding: 0;
+ width:100% !important;
+ float:left;
+ border-bottom: 1px solid #dfdfdf;
+}
+.jc-accord-heading label{
+ padding:9px;
+ background: #ededed;
+ color:#737373;
+}
+
+.jc-accord-heading.active label{
+ background: #737373;
+ color:#FFF;
+}
+
+.jc-accord-heading.jc-submenu-populate-archive{
+ border-bottom: none;
+}
+.jc-accord-heading.jc-submenu-populate-archive.active{
+ border-bottom: 1px solid #dfdfdf;
+}
+
+#jc-submenu-loading{
+ height:38px;
+ border: 1px solid #dfdfdf;
+ background: #ededed;
+ color:#737373;
+ line-height: 40px;
+ text-indent: 10px;
+ float:left;
+ width:367px;
+}
\ No newline at end of file
diff --git a/assets/js/ajax.js b/assets/js/ajax.js
new file mode 100644
index 0000000..981449c
--- /dev/null
+++ b/assets/js/ajax.js
@@ -0,0 +1,240 @@
+/**
+ * Admin Ajax Function
+ */
+(function($){
+
+ $.fn.jc_edit_menu = function(){
+
+ var id = JC_Submenu.get_menu_id($(this).attr('id'));
+ var _menu_item = $('#menu-item-'+id);
+
+ if(_menu_item.hasClass('menu-item-edit-inactive') && !_menu_item.hasClass('jc-submenu-populated')){
+
+ var id = JC_Submenu.get_menu_id(_menu_item.attr('id'));
+ var data = {
+ action: 'jcs_get_menu_item',
+ id: id
+ };
+
+ // show loading
+ $("").insertBefore(_menu_item.find('.menu-item-actions'));
+
+ jQuery.post(ajax_object.ajax_url, data, function(response) {
+
+ _menu_item.find("#jc-submenu-loading").remove();
+
+ $(response).insertBefore(_menu_item.find('.menu-item-actions'));
+
+ /**
+ * Display Active Menu Population Options
+ * @since 0.6
+ */
+ _menu_item.find('.jc-accord-heading').each(function(){
+
+ var accord_heading = $(this);
+ var id = JC_Submenu.get_menu_id(accord_heading.attr('id'));
+ var btn_handle = $('input', accord_heading);
+ var btn_label = $('label', accord_heading);
+
+ btn_handle.live('change', function(){
+
+ $('.jc-accord-heading', $('#menu-item-'+id)).removeClass('active');
+ $('.item-edit-panel', $('#menu-item-'+id)).hide();
+
+ if($(this).attr('checked') == 'checked'){
+ $( '.show-'+$(this).val() , $('#menu-item-'+id) ).show();
+ accord_heading.addClass('active');
+ }
+ });
+
+ btn_label.click(function(event){
+ $('.jc-accord-heading input:checked', $('#menu-item-'+id)).attr('checked', false);
+ btn_handle.attr('checked', 'checked').trigger('change');
+ event.preventDefault();
+ });
+
+ btn_handle.filter(":checked").trigger('change');
+ });
+
+ /**
+ * Display JC Submenu Options
+ * @since 0.6
+ */
+ _menu_item.find('input.jc-submenu-autopopulate').each(function(index){
+
+ var options_handle = $(this);
+ var id = JC_Submenu.get_menu_id(options_handle.attr('id'));
+
+ options_handle.live('change', function(){
+ if($(this).attr('checked') == 'checked'){
+ $( '#jc-submenu-populate-block-'+id).show();
+ $('.jc-submenu-active').show();
+ }else{
+ $( '#jc-submenu-populate-block-'+id).hide();
+ $('.jc-submenu-active').hide();
+ }
+ });
+
+ options_handle.filter(':checked').trigger('change');
+ });
+
+ /**
+ * Filter Taxonomy via selected Post Type
+ * @since 0.6
+ */
+ _menu_item.find('select[id^="edit-jc-submenu-populate-post"]').each(function(){
+
+ var post_select = $(this);
+ var id = JC_Submenu.get_menu_id(post_select.attr('id'));
+ var tax_select = $('select[id^="edit-jc-submenu-post-tax"]', $('#menu-item-'+id));
+ var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id));
+ var taxs = tax_select.clone();
+
+
+ post_select.live('change', function(){
+ var show_taxs = post_select.find(':selected').data('taxs').split(' ');
+ var selected = tax_select.find(':selected').val();
+
+ // tax_select = taxs.clone();
+ tax_select.empty();
+
+ $('option', taxs).each(function(index){
+
+ var val = $(this).val();
+
+ if($.inArray(val, show_taxs) != -1 || val == 0){
+
+ var clone_option = $(this).clone().attr('selected', false);
+
+ if(val == selected){
+ tax_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ tax_select.append(clone_option);
+ }
+ }else{
+ tax_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ // hide taxonomy filters if no options
+ /*if(tax_select.find('option').size() == 1){
+ tax_select.parent().hide();
+ }else{
+ tax_select.parent().show();
+ }*/
+
+ tax_select.trigger('change');
+ });
+
+ post_select.trigger('change');
+
+ });
+
+ /**
+ * Filter Terms depending on chosen taxonomy
+ * @since 0.6
+ */
+ _menu_item.find('select[id^="edit-jc-submenu-post-tax"]').each(function(){
+
+ var tax_select = $(this);
+ var id = JC_Submenu.get_menu_id(tax_select.attr('id'));
+ var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id));
+ var terms = term_select.clone();
+
+ tax_select.live('change', function(){
+
+ var tax = tax_select.find(':selected').val();
+ var selected = term_select.find(':selected').val();
+
+ term_select.empty();
+
+ $('option', terms).each(function(index){
+ var val = $(this).val();
+
+ if(tax == $(this).data('tax')){
+ var clone_option = $(this).clone().attr('selected', false);
+ if(val == selected){
+ term_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ term_select.append(clone_option);
+ }
+ }else{
+ term_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ /*if(term_select.find('option').size() == 1){
+ term_select.parent().hide();
+ }else{
+ term_select.parent().show();
+ }*/
+
+ });
+
+ tax_select.trigger('change');
+ });
+
+ /**
+ * Filter Taxonomy Terms depending on chosen taxonomy
+ * @since 0.6
+ */
+ _menu_item.find('select[id^="edit-jc-submenu-populate-tax"]').each(function(){
+
+ var tax_select = $(this);
+ var id = JC_Submenu.get_menu_id(tax_select.attr('id'));
+ var term_select = $('select[id^="edit-jc-submenu-tax-term"]', $('#menu-item-'+id));
+ var terms = term_select.clone();
+
+ tax_select.live('change', function(){
+
+ var tax = tax_select.find(':selected').val();
+ var selected = term_select.find(':selected').val();
+
+ term_select.empty();
+
+ $('option', terms).each(function(index){
+ var val = $(this).val();
+
+ if(tax == $(this).data('tax') || $(this).data('tax') == 0){
+ var clone_option = $(this).clone().attr('selected', false);
+ if(val == selected){
+ term_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ term_select.append(clone_option);
+ }
+ }else{
+ term_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ /*if(term_select.find('option').size() == 1){
+ term_select.parent().hide();
+ }else{
+ term_select.parent().show();
+ }*/
+
+ });
+
+ tax_select.trigger('change');
+ });
+ });
+
+ _menu_item.addClass('jc-submenu-populated');
+ }
+ }
+
+ /**
+ * JS Attach Item Template
+ *
+ * add before .menu-item-actions
+ */
+ $(document).ready(function(){
+
+ $('#menu-to-edit').on('click', 'a.item-edit', function(){
+ $(this).jc_edit_menu();
+ });
+
+ });
+
+
+})(jQuery);
\ No newline at end of file
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..9e43396
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,219 @@
+/**
+* JC Submenu Javascript
+*/
+
+var JC_Submenu = {
+
+ get_menu_id: function (id){
+ id= id.split("-");
+ id = id[id.length-1];
+ return id;
+ }
+
+};
+
+(function($){
+
+
+ /**
+ * Display Active Menu Population Options
+ * @since 0.2
+ */
+ $('.jc-accord-heading').each(function(){
+
+ var accord_heading = $(this);
+ var id = JC_Submenu.get_menu_id(accord_heading.attr('id'));
+ var btn_handle = $('input', accord_heading);
+ var btn_label = $('label', accord_heading);
+
+ btn_handle.live('change', function(){
+
+ $('.jc-accord-heading', $('#menu-item-'+id)).removeClass('active');
+ $('.item-edit-panel', $('#menu-item-'+id)).hide();
+
+ if($(this).attr('checked') == 'checked'){
+ $( '.show-'+$(this).val() , $('#menu-item-'+id) ).show();
+ accord_heading.addClass('active');
+ }
+ });
+
+ btn_label.click(function(event){
+ $('.jc-accord-heading input:checked', $('#menu-item-'+id)).attr('checked', false);
+ btn_handle.attr('checked', 'checked').trigger('change');
+ event.preventDefault();
+ });
+
+ btn_handle.filter(":checked").trigger('change');
+ });
+
+ /**
+ * Display JC Submenu Options
+ * @since 0.2
+ */
+ $('input.jc-submenu-autopopulate').each(function(index){
+
+ var options_handle = $(this);
+ var id = JC_Submenu.get_menu_id(options_handle.attr('id'));
+
+ options_handle.live('change', function(){
+ if($(this).attr('checked') == 'checked'){
+ $( '#jc-submenu-populate-block-'+id).show();
+ $('.jc-submenu-active').show();
+ }else{
+ $( '#jc-submenu-populate-block-'+id).hide();
+ $('.jc-submenu-active').hide();
+ }
+ });
+
+ options_handle.filter(':checked').trigger('change');
+ });
+
+ /**
+ * Filter Taxonomy via selected Post Type
+ * @since 0.2
+ */
+ $('select[id^="edit-jc-submenu-populate-post"]').each(function(){
+
+ var post_select = $(this);
+ var id = JC_Submenu.get_menu_id(post_select.attr('id'));
+ var tax_select = $('select[id^="edit-jc-submenu-post-tax"]', $('#menu-item-'+id));
+ var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id));
+ var taxs = tax_select.clone();
+
+
+ post_select.live('change', function(){
+ var show_taxs = post_select.find(':selected').data('taxs').split(' ');
+ var selected = tax_select.find(':selected').val();
+
+ // tax_select = taxs.clone();
+ tax_select.empty();
+
+ $('option', taxs).each(function(index){
+
+ var val = $(this).val();
+
+ if($.inArray(val, show_taxs) != -1 || val == 0){
+
+ var clone_option = $(this).clone().attr('selected', false);
+
+ if(val == selected){
+ tax_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ tax_select.append(clone_option);
+ }
+ }else{
+ tax_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ // hide taxonomy filters if no options
+ /*if(tax_select.find('option').size() == 1){
+ tax_select.parent().hide();
+ }else{
+ tax_select.parent().show();
+ }*/
+
+ tax_select.trigger('change');
+ });
+
+ post_select.trigger('change');
+
+ });
+
+ /**
+ * Filter Terms depending on chosen taxonomy
+ * @since 0.2
+ */
+ $('select[id^="edit-jc-submenu-post-tax"]').each(function(){
+
+ var tax_select = $(this);
+ var id = JC_Submenu.get_menu_id(tax_select.attr('id'));
+ var term_select = $('select[id^="edit-jc-submenu-post-term"]', $('#menu-item-'+id));
+ var terms = term_select.clone();
+
+ tax_select.live('change', function(){
+
+ var tax = tax_select.find(':selected').val();
+ var selected = term_select.find(':selected').val();
+
+ term_select.empty();
+
+ $('option', terms).each(function(index){
+ var val = $(this).val();
+
+ if(tax == $(this).data('tax')){
+ var clone_option = $(this).clone().attr('selected', false);
+ if(val == selected){
+ term_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ term_select.append(clone_option);
+ }
+ }else{
+ term_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ /*if(term_select.find('option').size() == 1){
+ term_select.parent().hide();
+ }else{
+ term_select.parent().show();
+ }*/
+
+ });
+
+ tax_select.trigger('change');
+ });
+
+ /**
+ * Filter Taxonomy Terms depending on chosen taxonomy
+ * @since 0.5.4
+ */
+ $('select[id^="edit-jc-submenu-populate-tax"]').each(function(){
+
+ var tax_select = $(this);
+ var id = JC_Submenu.get_menu_id(tax_select.attr('id'));
+ var term_select = $('select[id^="edit-jc-submenu-tax-term"]', $('#menu-item-'+id));
+ var terms = term_select.clone();
+
+ tax_select.live('change', function(){
+
+ var tax = tax_select.find(':selected').val();
+ var selected = term_select.find(':selected').val();
+
+ term_select.empty();
+
+ $('option', terms).each(function(index){
+ var val = $(this).val();
+
+ if(tax == $(this).data('tax') || $(this).data('tax') == 0){
+ var clone_option = $(this).clone().attr('selected', false);
+ if(val == selected){
+ term_select.append(clone_option.attr('selected', 'selected'));
+ }else{
+ term_select.append(clone_option);
+ }
+ }else{
+ term_select.find('option[value='+val+']').remove();
+ }
+ });
+
+ /*if(term_select.find('option').size() == 1){
+ term_select.parent().hide();
+ }else{
+ term_select.parent().show();
+ }*/
+
+ });
+
+ tax_select.trigger('change');
+ });
+
+
+ /**
+ * Document Ready
+ */
+ $(document).ready(function(){
+ $('.item-edit-panel').hide();
+ });
+
+})(jQuery);
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..1118caf
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "jc-submenu",
+ "version": "0.8.3",
+ "devDependencies": {
+ "grunt": "^0.4.5",
+ "grunt-contrib-clean": "^0.6.0",
+ "grunt-contrib-copy": "^0.7.0",
+ "grunt-contrib-cssmin": "^0.10.0",
+ "grunt-contrib-jshint": "~0.10.0",
+ "grunt-contrib-nodeunit": "~0.4.1",
+ "grunt-contrib-uglify": "^0.6.0"
+ }
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..c4ce129
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,19 @@
+
+
+
+
+
+ ./tests/
+
+
+
\ No newline at end of file
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..24690df
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,175 @@
+=== JC Submenu ===
+Contributors: jcollings
+Donate link:
+Tags: submenu, menu, dynamic, custom post type, taxonomy, child pages
+Requires at least: 3.0.1
+Tested up to: 4
+Stable tag: 0.8.3
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
+
+JC Submenu plugin allows you to automatically populate your navigation menus with custom post_types, taxonomies, or child pages.
+
+== Description ==
+
+JC Submenu plugin allows you to automatically populate your navigation menus with custom post_types, taxonomies, or child pages. An easy to use plugin created to be a lightweight menu extension.
+
+Also output a selected section of your dynamic menu through our advanced submenu widget.
+
+== Installation ==
+
+1. First grab a copy from [wordpress.org](http://downloads.wordpress.org/plugin/jc-submenu.zip).
+1. Extract the plugin to your wordpress plugins folder.
+1. Activate the plugin from your wordpress administration area (under the plugins section).
+1. You should thee should now be able to use JC Submenu Plugin.
+1. Optional - If your theme already has a custom walker specified for outputing your menu, JC Submenu will not automatically override it, to do this locate the file your theme outputs the menu (usually header.php) and look for "wp\_nav\_menu()", and pass an extra argument so it looks similar:
+
+`wp_nav_menu(array('walker' => new JC_Submenu_Nav_Walker()));`
+
+For further documentation on installing and using JC Submneu features can be found [here](http://jamescollings.co.uk/wordpress-plugins/jc-submenu/).
+
+== Frequently asked questions ==
+
+= How do i use the split menu functionality =
+
+The documentation for using the split menu functionality (widget, shortcode, action) can be found [here](http://jamescollings.co.uk/jc-submenu/resources/output-split-menu-section/)
+
+= How do i output a section of menu =
+
+The documentation for displaying a section of menu (widget, shortcode, action) can be found [here](http://jamescollings.co.uk/jc-submenu/resources/how-to-output-a-section-of-a-wordpress-menu/)
+
+= How do i automatically populate menu items =
+
+The documentation for automatically populating menu items can be found [here](http://jamescollings.co.uk/jc-submenu/resources/how-to-automatically-populate-wordpress-submenus/)
+
+= What Actions and filters are avaliable in this plugin =
+
+A list of all actions and filters can be found [here](http://jamescollings.co.uk/jc-submenu/sections/actions-filters/)
+
+
+== Screenshots ==
+
+1. JC Submenu, Post population options
+2. JC Submenu, Taxonomy population options
+3. JC Submenu, Page children population options
+4. JC Submenu, Advanced Submenu Widget Options
+
+== Changelog ==
+
+**0.8.3**
+
+* Fix add_post_meta not set to unique when saving menu items, causing multiple entries to be saved.
+
+**0.8.2**
+
+* Fix filter jcs/enable_public_walker to actually be used, as before it was not able to be overwritten by themes only plugins
+
+**0.8.1**
+
+* Added jcs/split_menu/populated_elements, jcs/section_menu/populated_elements, jcs/populated_elements to allow modification of populated menu elements
+* Updated Readme to be tested upto wp 4
+
+**0.8**
+
+* Fix error when populating with an empty array of posts
+* Add jcs/enable_public_walker filter to disable/enable the public walker to allow jc submenu be used with other custom walkers.
+* Add jcs/split_widget_title to overwrite split menu title
+* Add {{PARENT_TITLE}} template tags to show the active parent item in the split menu widget.
+
+**0.7.2**
+
+* Added filter to change submenu level class jcs/menu_level_class, return array of classes
+* Added the option to populate by post date archive
+* Added post date archive grouping by year
+
+**0.7.1**
+
+* Fixed infinite loop error when passed badly formed menu items.
+
+**0.7**
+
+* Simplified dynamic menu population
+* Added the ability to replace the current item with dynamically populated items
+
+**0.6.2**
+
+* Fixed clone() warning
+* Added trigger_depth to split menu
+* Fixed Menu Ordering
+* Updated FAQ Section
+
+**0.6.1**
+
+* Renamed filter from jci/menu_item_args to jcs/menu_item_args
+
+**0.6**
+
+* Add menu item filters jcs/item_title, jcs/item_url, jcs/page_item_title, jcs/page_item_url, jcs/post_item_title, jcs/post_item_url, jcs/term_item_title, jcs/term_item_url
+* Add admin-menu notice to show if item is dynamically populated
+* Add compatability to other plugins who use a custom admin walker
+* Add setting to disable ajax menu edit
+* Add menu item argument filters jci/menu_item_args to allow customisation of output per item
+
+**0.5.5**
+
+* Add class filter jcs/item_classes
+* Add class filter jcs/term_item_classes
+* Add class filter jcs/post_item_classes
+* Add class filter jcs/page_item_classes
+* Add WP_Query arguments filter jcs/post_query_args, jcs/post_$menu-item-id_query_args
+* Add get_pages arguments filter jcs/page_query_args, jcs/page_$menu-item-id_query_args
+* Add get_terms arguments filter jcs/term_query_args, jcs/term_$menu-item-id_query_args
+* Ouput post_type with hierarchy
+* Removed php strict warnings
+
+**0.5.4**
+
+* Added option into populate by taxonomy to set the term parent
+
+**0.5.3**
+
+* Removed PHP Warning for imploding false in exclude terms list
+* Remove PHP Warning for missing array in exclude pages list
+
+**0.5.2**
+
+* Fixed SubmenuWalker replaces order_by with orderby
+* Added in basic CSV input taxonomy term exclusion.
+
+**0.5**
+
+* Added option to limit taxonomy depth
+* Added option to exclude child pages
+* Added Split menu shortcode
+* Added Menu section shortcode
+* Fixed possible function conflict
+* Fixed menu depth
+* Fixed split menu
+* Fixed menu section
+* Fixed post_type / page with taxonomy not highlighting menu item
+
+**0.4.1**
+
+* Added child page order support
+* Fixed Javascript jumping bug
+* Added version to js,css to fix cache problem
+* Added documentation notification link on plugin update
+* Added Menu Section Widget
+
+**0.4**
+
+* Added Split menu output action jcs/split_menu, Menu Section output action jcs/split_menu to allow theme developers to output submenus.
+
+**0.3**
+
+* Split Menu Widget Added
+
+**0.2**
+
+* Interface update
+* Custom post type population can now be filtered by a Taxonomy
+* Javascript update
+* Compatability with wordpress 3.6
+
+
+== Upgrade notice ==
diff --git a/screenshot-1.png b/screenshot-1.png
new file mode 100644
index 0000000..d8fab11
Binary files /dev/null and b/screenshot-1.png differ
diff --git a/screenshot-2.png b/screenshot-2.png
new file mode 100644
index 0000000..eea7d1c
Binary files /dev/null and b/screenshot-2.png differ
diff --git a/screenshot-3.png b/screenshot-3.png
new file mode 100644
index 0000000..4f9cbcc
Binary files /dev/null and b/screenshot-3.png differ
diff --git a/screenshot-4.png b/screenshot-4.png
new file mode 100644
index 0000000..8166e51
Binary files /dev/null and b/screenshot-4.png differ
diff --git a/submenu.php b/submenu.php
new file mode 100644
index 0000000..e45bdff
--- /dev/null
+++ b/submenu.php
@@ -0,0 +1,279 @@
+
+ * @version 0.8.3
+ */
+class JCSubmenu{
+
+ var $version = '0.8.3';
+ var $version_check = 70;
+ var $plugin_dir = false;
+ var $plugin_url = false;
+ var $prefix = 'jc-submenu';
+ var $edit_walker = false;
+ var $public_walker = true;
+
+ /**
+ * Setup plugin
+ * @return void
+ */
+ function __construct(){
+
+ $this->plugin_dir = plugin_dir_path( __FILE__ );
+ $this->plugin_url = plugins_url( '/', __FILE__ );
+
+ $this->load_modules();
+
+ // add plugin hooks
+ add_action('jcs/menu_section', array($this, 'output_menu_section'), 10, 2);
+ add_action('jcs/split_menu', array($this, 'output_split_menu'), 10, 2);
+
+ // add plugin shortcodes
+ add_shortcode( 'jcs_split_menu', array($this, 'split_menu_shortcode') );
+ add_shortcode( 'jcs_menu_section', array($this, 'menu_section_shortcode') );
+
+ // init menu attachment
+ add_action('init', array($this, 'init'));
+ }
+
+ /**
+ * Set which type of attachment is used
+ * @return void
+ */
+ public function init(){
+
+ $this->public_walker = apply_filters('jcs/enable_public_walker', false );
+
+ if(!$this->public_walker){
+ add_filter( 'wp_nav_menu_objects', array( $this, 'populate_menu_items' ));
+ }else{
+ add_filter( 'wp_nav_menu_args', array( $this, 'attach_menu_walker' ));
+ }
+ }
+
+ /**
+ * Attach custom nav walker
+ *
+ * Hook into theme menu, attach custom walker
+ *
+ * @param array $args
+ * @return array
+ */
+ function attach_menu_walker($args){
+ if(empty($args['walker'])){
+ $args['walker'] = new JC_Submenu_Nav_Walker();
+ }
+ return $args;
+ }
+
+ /**
+ * Add menu items without using a custom walker
+ *
+ * @param array $menu_items
+ * @return array new menu items
+ */
+ function populate_menu_items($menu_items = array()){
+
+ $walker = new JC_Submenu_Nav_Walker();
+ $menu_items = $walker->attach_elements($menu_items);
+ $menu_items = $walker->_process_menu($menu_items);
+
+ return $menu_items;
+ }
+
+ /**
+ * Load Required Modules
+ * @return void
+ */
+ function load_modules(){
+
+ include 'walkers/AdminMenuWalker.php';
+ include 'walkers/SubmenuWalker.php';
+ include 'walkers/DropdownWalker.php';
+ include 'widgets/SectionMenuWidget.php';
+ include 'widgets/SplitMenuWidget.php';
+ include 'SubmenuModel.php';
+ SubmenuModel::init($this);
+
+ include 'SubmenuAdmin.php';
+ new SubmenuAdmin($this);
+ }
+
+ /**
+ * Slit Menu Section Shortcode
+ *
+ * Display a dynamic split menu section via wordpress shortcode tags
+ *
+ * @param array $atts
+ * @return string
+ */
+ function split_menu_shortcode($atts){
+ extract(shortcode_atts( array(
+ 'hierarchy' => 1,
+ 'start' => 0,
+ 'depth' => 5,
+ 'show_parent' => 0,
+ 'menu' => false,
+ 'trigger_depth' => 0
+ ), $atts ));
+
+ if(!$menu)
+ return false;
+
+ ob_start();
+
+ do_action('jcs/split_menu', $menu, array(
+ 'hierarchy' => $hierarchy,
+ 'start' => $start,
+ 'depth' => $depth,
+ 'show_parent' => $show_parent,
+ 'trigger_depth' => $trigger_depth
+ ));
+
+ $output = ob_get_contents();
+ ob_end_clean();
+ return $output;
+ }
+
+ /**
+ * Menu Section Shortcode
+ *
+ * Display section of menu via wordpress shortcode tags
+ *
+ * @param array $atts
+ * @return string
+ */
+ function menu_section_shortcode($atts){
+ extract(shortcode_atts( array(
+ 'hierarchy' => 1,
+ 'start' => 0,
+ 'depth' => 5,
+ 'show_parent' => 0,
+ 'menu' => false
+ ), $atts ));
+
+ if(!$menu)
+ return false;
+
+ ob_start();
+
+ do_action('jcs/menu_section', $menu, array(
+ 'hierarchy' => $hierarchy,
+ 'start' => $start,
+ 'depth' => $depth,
+ 'show_parent' => $show_parent,
+ ));
+
+ $output = ob_get_contents();
+ ob_end_clean();
+ return $output;
+ }
+
+ /**
+ * Output menu section
+ *
+ * Display a section of the selected menu in your theme
+ *
+ * @param string $menu
+ * @param array $args
+ * @return void
+ */
+ function output_menu_section($menu, $args = array()){
+
+ $debug = isset($args['debug']) ? $args['debug'] : false;
+ $hierarchical = isset($args['hierarchy']) ? $args['hierarchy'] : 1;
+ $start = isset($args['start']) ? $args['start'] : 0;
+ $depth = isset($args['depth']) ? $args['depth'] : 5;
+ $show_parent = isset($args['show_parent']) ? $args['show_parent'] : 0;
+
+ $options = array('menu' => $menu, 'walker' => new JC_Submenu_Nav_Walker(array(
+ 'debug' => $debug,
+ 'section_menu' => true,
+ 'menu_item' => $start,
+ 'menu_depth' => $depth,
+ 'show_parent' => $show_parent
+ ))
+ );
+
+ if(isset($args['menu_class']))
+ $options['menu_class'] = $args['menu_class'];
+
+ if(isset($args['menu_id']))
+ $options['menu_id'] = $args['menu_id'];
+
+ if(isset($args['container']))
+ $options['container'] = $args['container'];
+
+ if(isset($args['container_id']))
+ $options['container_id'] = $args['container_id'];
+
+ if(isset($args['container_class']))
+ $options['container_class'] = $args['container_class'];
+
+ wp_nav_menu($options);
+ }
+
+ /**
+ * Output Split Menu
+ *
+ * Display a dynamic section of the selected menu in your theme relative to your current page
+ *
+ * @param string $menu
+ * @param array $args
+ * @return void
+ */
+ function output_split_menu($menu, $args = array()){
+
+ $hierarchical = isset($args['hierarchy']) ? $args['hierarchy'] : 1;
+ $menu_start = isset($args['start']) ? $args['start'] : 1;
+ $menu_depth = isset($args['depth']) ? $args['depth'] : 5;
+ $show_parent = isset($args['show_parent']) ? $args['show_parent'] : 0;
+ $trigger_depth = isset($args['trigger_depth']) ? $args['trigger_depth'] : 0;
+ $parent_label = isset($args['parent_label']) ? $args['parent_label'] : false;
+
+ $options = array(
+ 'menu' => $menu, 'walker' => new JC_Submenu_Nav_Walker(array(
+ 'hierarchical' => $hierarchical,
+ 'menu_start' => $menu_start,
+ 'menu_depth' => $menu_depth,
+ 'show_parent' => $show_parent,
+ 'trigger_depth' => $trigger_depth,
+ 'parent_label' => $parent_label,
+ 'split_menu' => true
+ ))
+ );
+
+ if(isset($args['menu_class']))
+ $options['menu_class'] = $args['menu_class'];
+
+ if(isset($args['menu_id']))
+ $options['menu_id'] = $args['menu_id'];
+
+ if(isset($args['container']))
+ $options['container'] = $args['container'];
+
+ if(isset($args['container_id']))
+ $options['container_id'] = $args['container_id'];
+
+ if(isset($args['container_class']))
+ $options['container_class'] = $args['container_class'];
+
+ wp_nav_menu($options);
+ }
+}
+
+$GLOBALS['jcsubmenu'] = new JCSubmenu();
+?>
\ No newline at end of file
diff --git a/tests/DynamicItemsTest.php b/tests/DynamicItemsTest.php
new file mode 100644
index 0000000..67330df
--- /dev/null
+++ b/tests/DynamicItemsTest.php
@@ -0,0 +1,510 @@
+submenu = $GLOBALS['jcsubmenu'];
+ }
+
+ function testElementDepths(){
+ $walker = new JC_Submenu_Nav_Walker();
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+
+ $output = $walker->set_elements_depth($elements);
+ $this->assertEquals(8, count($elements));
+ $this->assertEquals($elements[0]->depth, 0);
+ $this->assertEquals($elements[1]->depth, 1);
+ $this->assertEquals($elements[2]->depth, 1);
+ $this->assertEquals($elements[3]->depth, 1);
+ $this->assertEquals($elements[4]->depth, 2);
+ $this->assertEquals($elements[5]->depth, 2);
+ $this->assertEquals($elements[6]->depth, 3);
+ $this->assertEquals($elements[7]->depth, 3);
+ }
+
+ function testElementState01(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+
+ /**
+ * Top level parent
+ */
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ function testElementState02(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+
+ /**
+ * Second level parent
+ */
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'classes' => array('current-menu-parent', 'current-menu-ancestor'),
+ 'current_item_ancestor' => 1,
+ 'current_item_parent' => 1,
+ 'split_section' => 1
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ function testElementState03(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+
+ /**
+ * Third level parent
+ */
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'classes' => array('current-menu-ancestor'),
+ 'split_section' => 1,
+ 'current_item_ancestor' => 1,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ 'classes' => array('current-menu-parent', 'current-menu-ancestor'),
+ 'current_item_parent' => 1,
+ 'current_item_ancestor' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+
+ }
+
+ function testElementState04(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+ /**
+ * Fourth Level Parent
+ */
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ // no parent
+ (object)array(
+ 'menu_item_parent' => 9,
+ 'db_id' => 9,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'classes' => array('current-menu-ancestor'),
+ 'current_item_ancestor' => 1,
+ 'split_section' => 1
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 2,
+ 'classes' => array('current-menu-ancestor'),
+ 'current_item_ancestor' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ // lvl 2
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'classes' => array('current-menu-parent', 'current-menu-ancestor'),
+ 'current_item_ancestor' => 1,
+ 'current_item_parent' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ // lvl 3
+ (object)array(
+ 'menu_item_parent' => 5,
+ 'db_id' => 7,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 6,
+ 'db_id' => 8,
+ ),
+ // no parent
+ (object)array(
+ 'menu_item_parent' => 9,
+ 'db_id' => 9,
+ ),
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ /**
+ * Test Single Menu Item who is current
+ */
+ function testElementState05(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+ /**
+ * Fourth Level Parent
+ */
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ )
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1,
+ 'split_section' => 1
+ )
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ /**
+ * Test Single Menu Item not current
+ */
+ function testElementState06(){
+
+ $walker = new JC_Submenu_Nav_Walker();
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ )
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ )
+ );
+
+ $output = $walker->_set_elements_state($elements);
+ $this->assertEquals($result, $output);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/SectionMenuTest.php b/tests/SectionMenuTest.php
new file mode 100644
index 0000000..f80c3e5
--- /dev/null
+++ b/tests/SectionMenuTest.php
@@ -0,0 +1,177 @@
+submenu = $GLOBALS['jcsubmenu'];
+ }
+
+ /**
+ * Basic Menu Section 1/2
+ */
+ function testSectionMenu01(){
+
+ $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 1, 'menu_depth' => 1));
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_menu_section($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ /**
+ * Basic Menu Section 2/2
+ */
+ function testSectionMenu02(){
+
+ $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 2, 'menu_depth' => 1));
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_menu_section($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ /**
+ * Test Show Parent 1/2
+ */
+ function testSectionMenu03(){
+
+ $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 1, 'menu_depth' => 1, 'show_parent' => 1));
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1,
+ 'menu_depth' => 0
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_menu_section($elements);
+ $this->assertEquals($result, $output);
+ }
+
+ /**
+ * Test Show Parent 2/2
+ */
+ function testSectionMenu04(){
+
+ $walker = new JC_Submenu_Nav_Walker(array('menu_item' => 2, 'menu_depth' => 1, 'show_parent' => 1));
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ 'menu_depth' => 0
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 4,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_menu_section($elements);
+ $this->assertEquals($result, $output);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/SplitMenuTest.php b/tests/SplitMenuTest.php
new file mode 100644
index 0000000..200e524
--- /dev/null
+++ b/tests/SplitMenuTest.php
@@ -0,0 +1,577 @@
+submenu = $GLOBALS['jcsubmenu'];
+ }
+
+ public function stripResults($elements){
+ foreach($elements as $elm){
+ if(isset($elm->classes)){
+ unset($elm->classes);
+ }
+ if(isset($elm->current_item_ancestor)){
+ unset($elm->current_item_ancestor);
+ }
+ if(isset($elm->current_item_parent)){
+ unset($elm->current_item_parent);
+ }
+ }
+ return $elements;
+ }
+
+ public function orderItems($elements){
+ usort($elements, array($this, 'usortElement'));
+ return $elements;
+ }
+
+ public function usortElement($a, $b){
+ return $a->db_id - $b->db_id;
+ }
+
+ /**
+ * Top Level Split Test 1/2
+ * Test a basic split menu from menu item 1
+ */
+ public function testSplitMenu01(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'current' => 1,
+ 'split_section' => 1,
+ 'menu_depth' => 0
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'menu_depth' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 ));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+ }
+
+ /**
+ * Top Leve Split Test 2/2
+ * Test a basic split menu from menu item 2
+ */
+ public function testSplitMenu02(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ 'current' => 1
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ 'current' => 1,
+ 'menu_depth' => 0,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ 'menu_depth' => 1,
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 ));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+ }
+
+ /**
+ * Top Level Split Test with parent 1/2
+ * Test a basic split menu from menu item 1
+ */
+ public function testSplitMenu03(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'split_section' => 1,
+ 'menu_depth' => 0,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'menu_depth' => 1,
+ 'current' => 1,
+ 'split_section' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ 'menu_depth' => 1
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 ));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $output = $this->stripResults($output);
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+
+ }
+
+ /**
+ * Top Leve Split Test with parent 2/2
+ * Test a basic split menu from menu item 2
+ */
+ public function testSplitMenu04(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ 'menu_depth' => 0,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'menu_depth' => 1,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ 'menu_depth' => 1,
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'menu_start' => 1 ));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $output = $this->stripResults($output);
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+
+ }
+
+ /**
+ * First child split menu test 1/2
+ */
+ public function testSplitMenu05(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ 'split_section' => 1,
+ 'menu_depth' => 0,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ 'current' => 1,
+ 'split_section' => 1,
+ 'menu_depth' => 1,
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $output = $this->stripResults($output);
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+
+ }
+
+ /**
+ * First child split menu test 2/2
+ */
+ public function testSplitMenu06(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ 'current' => 1
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ 'split_section' => 1,
+ 'menu_depth' => 0,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ 'current' => 1,
+ 'split_section' => 1,
+ 'menu_depth' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ 'menu_depth' => 1,
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $output = $this->stripResults($output);
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+
+ }
+
+ /**
+ * Empty Split Menu Test
+ */
+ public function testSplitMenu07(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+ $this->assertEmpty($output);
+ }
+
+ /**
+ * Test current item with missing parent item
+ */
+ public function testSplitMenu08(){
+
+ $elements = array(
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 1,
+ ),
+ (object)array(
+ 'menu_item_parent' => 0,
+ 'db_id' => 2,
+ ),
+ // lvl 1
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 3,
+ ),
+ (object)array(
+ 'menu_item_parent' => 1,
+ 'db_id' => 4,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 5,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 6,
+ ),
+ (object)array(
+ 'menu_item_parent' => 2,
+ 'db_id' => 7,
+ ),
+ (object)array(
+ 'menu_item_parent' => 8,
+ 'db_id' => 8,
+ 'current' => 1
+ ),
+ );
+
+ $result = array(
+ (object)array(
+ 'menu_item_parent' => 8,
+ 'db_id' => 8,
+ 'current' => 1,
+ 'split_section' => 1
+ ),
+ );
+
+ $walker = new JC_Submenu_Nav_Walker(array('split_menu' => true, 'trigger_depth' => 0, 'menu_start' => 1, 'menu_depth' => 1, 'show_parent' => false));
+
+ $elements = $walker->_set_elements_state($elements);
+ $elements = $walker->set_elements_depth($elements, 0, true);
+ $output = $walker->_process_split_menu($elements);
+
+ $output = $this->stripResults($output);
+ $this->assertEquals($this->orderItems($result), $this->orderItems($output));
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..733ef39
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,16 @@
+ array("jc-submenu/submenu.php" ),
+);
+
+if( file_exists( $path ) ) {
+ require_once $path;
+} else {
+ exit( "Couldn't find path to wordpress-tests/bootstrap.php\n" );
+}
\ No newline at end of file
diff --git a/views/edit.php b/views/edit.php
new file mode 100644
index 0000000..bd26b77
--- /dev/null
+++ b/views/edit.php
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/views/settings.php b/views/settings.php
new file mode 100644
index 0000000..532f232
--- /dev/null
+++ b/views/settings.php
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/walkers/AdminMenuWalker.php b/walkers/AdminMenuWalker.php
new file mode 100644
index 0000000..64086c4
--- /dev/null
+++ b/walkers/AdminMenuWalker.php
@@ -0,0 +1,205 @@
+ $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth;
+
+ $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
+
+ ob_start();
+ $item_id = esc_attr( $item->ID );
+ $removed_args = array(
+ 'action',
+ 'customlink-tab',
+ 'edit-menu-item',
+ 'menu-item',
+ 'page-tab',
+ '_wpnonce',
+ );
+
+ $original_title = '';
+ if ( 'taxonomy' == $item->type ) {
+ $original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' );
+ if ( is_wp_error( $original_title ) )
+ $original_title = false;
+ } elseif ( 'post_type' == $item->type ) {
+ $original_object = get_post( $item->object_id );
+ $original_title = $original_object->post_title;
+ }
+
+ $classes = array(
+ 'menu-item menu-item-depth-' . $depth,
+ 'menu-item-' . esc_attr( $item->object ),
+ 'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'),
+ );
+
+ $title = $item->title;
+
+ if ( ! empty( $item->_invalid ) ) {
+ $classes[] = 'menu-item-invalid';
+ /* translators: %s: title of menu item which is invalid */
+ $title = sprintf( __( '%s (Invalid)' ), $item->title );
+ } elseif ( isset( $item->post_status ) && 'draft' == $item->post_status ) {
+ $classes[] = 'pending';
+ /* translators: %s: title of menu item in draft status */
+ $title = sprintf( __('%s (Pending)'), $item->title );
+ }
+
+ $title = empty( $item->label ) ? $title : $item->label;
+
+ ?>
+ hierarchical = isset($args['hierarchical']) && $args['hierarchical'] == 0 ? 0 : 1;
+ $this->split_menu = isset($args['split_menu']) ? true : false;
+ $this->section_menu = isset($args['section_menu']) && is_bool($args['section_menu']) ? $args['section_menu'] : false;
+
+ // Display Split Menu Section
+ $this->menu_start_item = isset($args['menu_item']) ? intval($args['menu_item']) : 0;
+ $this->menu_start = isset($args['menu_start']) ? intval($args['menu_start']) : 0;
+ $this->menu_depth = isset($args['menu_depth']) ? intval($args['menu_depth']) : 5;
+ $this->show_parent = isset($args['show_parent']) && $args['show_parent'] == 1 ? 1 : 0;
+ $this->split_trigger_depth = isset($args['trigger_depth']) && $args['trigger_depth'] > 0 ? $args['trigger_depth'] : 0;
+ $this->parent_label = isset($args['parent_label']) ? $args['parent_label'] : false;
+ }
+
+ function replace_template_vars($output = ''){
+
+ $output = str_replace('{{PARENT_TITLE}}', $this->active_title, $output);
+ return $output;
+ }
+
+ function start_el( &$output, $item, $depth = 0, $args = array(), $current_object_id = 0 ) {
+
+ // clone to unlink from $args
+ if(is_object($args)){
+ $temp = clone($args);
+ }else{
+ $temp = $args;
+ }
+
+ $item_args = apply_filters( 'jcs/menu_item_args', $temp, $item);
+ parent::start_el($output, $item, $depth, $item_args, $current_object_id);
+ }
+
+ function end_el( &$output, $item, $depth = 0, $args = array() ) {
+
+ // clone to unlink from $args
+ if(is_object($args)){
+ $temp = clone($args);
+ }else{
+ $temp = $args;
+ }
+
+ $item_args = apply_filters( 'jcs/menu_item_args', $temp, $item);
+ parent::end_el($output, $item, $depth, $item_args);
+ }
+
+ function start_lvl( &$output, $depth = 0, $args = array() ) {
+
+ if( $this->hierarchical == 1 ){
+
+ $classes = apply_filters( 'jcs/menu_level_class', array('sub-menu'), $depth, $args);
+ $level_classes = "";
+ $indent = str_repeat("\t", $depth);
+
+ if(is_array($classes) && !empty($classes)){
+ $level_classes = implode(" ", $classes);
+ }
+
+ $output .= "\n$indent\n";
+ }
+ }
+
+ function end_lvl( &$output, $depth = 0, $args = array() ) {
+
+ if( $this->hierarchical == 1 ){
+
+ $indent = str_repeat("\t", $depth);
+ $output .= "$indent \n";
+ }
+ }
+
+ /**
+ * Display array of elements hierarchically.
+ *
+ * It is a generic function which does not assume any existing order of
+ * elements. max_depth = -1 means flatly display every element. max_depth =
+ * 0 means display all levels. max_depth > 0 specifies the number of
+ * display levels.
+ *
+ * @since 2.1.0
+ *
+ * @param array $elements
+ * @param int $max_depth
+ * @return string
+ */
+ function walk( $elements, $max_depth) {
+
+ $args = array_slice(func_get_args(), 2);
+ $output = '';
+
+ if ($max_depth < -1) //invalid parameter
+ return $output;
+
+ if (empty($elements)) //nothing to walk
+ return $output;
+
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+
+ // flat display
+ if ( -1 == $max_depth ) {
+ $empty_array = array();
+ foreach ( $elements as $e )
+ $this->display_element( $e, $empty_array, 1, 0, $args, $output );
+ return $output;
+ }
+
+ /**
+ * Loop through all menu items checking to see if if any items have been
+ * marked for auto population using this plugin
+ */
+
+ global $jcsubmenu;
+
+ if($jcsubmenu->public_walker){
+ $elements = $this->attach_elements($elements);
+ }
+
+ $elements = $this->_process_menu($elements);
+
+ // escape if no elements are left
+ if(empty($elements)){
+ return false;
+ }
+
+ /*
+ * need to display in hierarchical order
+ * separate elements into two buckets: top level and children elements
+ * children_elements is two dimensional array, eg.
+ * children_elements[10][] contains all sub-elements whose parent is 10.
+ */
+ $top_level_elements = array();
+ $children_elements = array();
+
+ foreach ( $elements as $e) {
+
+ if ( 0 == $e->$parent_field ){
+ $top_level_elements[] = $e;
+ }else{
+ $children_elements[ $e->$parent_field ][] = $e;
+ }
+ }
+
+ /*
+ * when none of the elements is top level
+ * assume the first one must be root of the sub elements
+ */
+ if ( empty($top_level_elements) ) {
+
+ $first = array_slice( $elements, 0, 1 );
+ $root = $first[0];
+
+ $top_level_elements = array();
+ $children_elements = array();
+ foreach ( $elements as $e) {
+ if ( $root->$parent_field == $e->$parent_field )
+ $top_level_elements[] = $e;
+ else
+ $children_elements[ $e->$parent_field ][] = $e;
+ }
+ }
+
+ foreach ( $top_level_elements as $e )
+ $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
+
+ /*
+ * if we are displaying all levels, and remaining children_elements is not empty,
+ * then we got orphans, which should be displayed regardless
+ */
+ if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
+ $empty_array = array();
+ foreach ( $children_elements as $orphans )
+ foreach( $orphans as $op )
+ $this->display_element( $op, $empty_array, 1, 0, $args, $output );
+ }
+
+ return $output;
+ }
+
+ public function attach_elements($elements){
+
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+
+ // copy to new array to keep menu item order
+ $new_elements = array();
+ foreach($elements as $k => $e){
+ $break = false;
+
+ // Hide element for logged in users
+ if(!is_user_logged_in() && intval(SubmenuModel::get_meta($e->$id_field, 'admin')) == 1){
+ unset($elements[$k]);
+ $break = true;
+ }
+
+ if(!$break){
+ $new_elements[] = $e;
+ $current_dynamic_parent = false;
+
+ // check to see if auto populate flag has been set
+ if(SubmenuModel::get_meta($e->$id_field, 'autopopulate') == 1){
+
+ $type = SubmenuModel::get_meta($e->$id_field, 'populate-type');
+ $value = SubmenuModel::get_meta($e->$id_field, 'populate-value');
+
+ /**
+ * Added: 6/3/14
+ * Replace dynamic item with populated menu items
+ * TODO: Fix overriding of all menu items
+ */
+ $parent = false;
+ $childpop = SubmenuModel::get_meta($e->$id_field, 'childpop');
+ if($childpop == 1){
+ $parent = true;
+ array_pop($new_elements);
+ }
+
+ if($type == 'post'){
+ $new_elements = array_merge($new_elements, $this->_populate_post_items($e, $value, $parent));
+ }elseif($type == 'page'){
+ $new_elements = array_merge($new_elements, $this->_populate_page_items($e, $value, $parent));
+ }elseif($type == 'tax'){
+ $new_elements = array_merge($new_elements, $this->_populate_tax_items($e, $value, $parent));
+ }elseif($type == 'archive'){
+ $new_elements = array_merge($new_elements, $this->_populate_archive_items($e, $value, $parent));
+ }
+ }
+ }
+ }
+
+ $elements = $new_elements;
+
+ // filter to allow modification of populated menu items, e.g. set current menu item
+ if($this->split_menu){
+ $elements = apply_filters( 'jcs/split_menu/populated_elements', $elements);
+ }elseif($this->section_menu){
+ $elements = apply_filters( 'jcs/section_menu/populated_elements', $elements);
+ }
+
+ $elements = apply_filters( 'jcs/populated_elements', $elements);
+
+ return $elements;
+ }
+
+ public function _process_menu($elements = array()){
+
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+
+ // set menu item status
+ $elements = $this->_set_elements_state($elements);
+
+ // Set Menu Item Depth
+ $elements = $this->set_elements_depth($elements, 0, true);
+
+ if($this->section_menu || $this->split_menu){
+
+ // start template replacement function
+ add_filter( 'jcs/split_widget_title', array($this, 'replace_template_vars'));
+
+ // process section of menu
+ if($this->section_menu == true){
+
+ $new_elems = $this->_process_menu_section($elements);
+ }
+
+ // process split menu
+ if($this->split_menu == true){
+
+ $new_elems = $this->_process_split_menu($elements);
+ }
+
+ // process elements to display
+ foreach($new_elems as $k => $elm){
+
+ // add data to elements
+ if($elm->menu_depth > $this->menu_start){
+
+ if($elm->menu_depth >= ($this->menu_start + $this->menu_depth)){
+ // remove items that are too deep
+ unset($new_elems[$k]);
+ }
+ }elseif($elm->menu_depth == $this->menu_start){
+
+ // change the parent title
+ if($this->show_parent){
+ $this->active_title = $new_elems[$k]->title;
+
+ if($this->parent_label){
+ $new_elems[$k]->title = $this->parent_label;
+ }
+ }
+
+ // need to change to parent = 0
+ $new_elems[$k]->$parent_field = 0;
+ }else{
+
+ // set the active title if split menu and the current parent is not being shown
+ if(!$this->show_parent && $this->split_menu){
+ $this->active_title = $new_elems[$k]->title;
+ }
+
+ // unset elements beneath
+ unset($new_elems[$k]);
+ }
+ }
+
+ $elements = $new_elems;
+ }
+
+ return $elements;
+ }
+
+ public function _process_menu_section($elements = array()){
+
+ $new_elems = array();
+
+ foreach($elements as $item){
+ if(($this->menu_start_item == $item->db_id && $this->show_parent == 1) || $item->menu_item_parent == $this->menu_start_item || in_array($item->menu_item_parent, $this->_section_ids)){
+
+ // set depth start from first item
+ if(empty($new_elems)){
+ $this->menu_start = $item->menu_depth;
+
+ if($this->show_parent)
+ $this->menu_depth++;
+ }
+
+ $new_elems[] = $item;
+
+ if(!in_array($item->db_id, $this->_section_ids)){
+ $this->_section_ids[] = $item->db_id;
+ }
+ }
+ }
+
+ return $new_elems;
+ }
+
+ public function _process_split_menu($elements = array()){
+
+ $new_elems = array();
+ $old_elems = $elements;
+ $test_elms = $elements;
+ $section_parents = array();
+ $parent_elem = false;
+ $parent_count = 0;
+ $keep_element_ids = array();
+ $keep_element_parents = array();
+ $selected_depth = 0;
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+
+ // get relevent parent id
+ if($this->menu_start > 0){
+ foreach($old_elems as $elm){
+
+ /**
+ * Added: 6/3/14
+ * Get current menu item
+ */
+ if((isset($elm->classes) && in_array('current-menu-item', $elm->classes)) || ( isset($elm->current) && $elm->current == 1)){
+ $keep_element_ids[] = $elm->$id_field;
+ $keep_element_parents[] = $elm->$parent_field;
+ $selected_depth = isset($elm->menu_depth) ? $elm->menu_depth: 0;
+ }
+
+ if(in_array($elm->$id_field, $this->selected_section_ids)){
+
+ /**
+ * Added: 6/3/14
+ * Comment out if statement
+ */
+ // if($elm->menu_depth == $this->menu_start - 1){
+ $new_elems[] = $elm;
+ $section_parents[] = $elm->$id_field;
+ // }
+ }
+ }
+
+ /**
+ * Added: 6/3/14
+ * Build a list of ids
+ * Display Menu items which are only one item deeper than current selection
+ */
+ $break = false;
+ while(!$break){
+ $break = true;
+ foreach($old_elems as $elm){
+ if(in_array($elm->$parent_field, $keep_element_ids) && !in_array($elm->$id_field, $keep_element_ids) &&
+ ($this->split_trigger_depth == 0 || $elm->menu_depth <= $selected_depth + $this->split_trigger_depth)){
+ $keep_element_ids[] = $elm->$id_field;
+ $break = false;
+ }
+ }
+ }
+
+ /**
+ * Added: 6/3/14
+ * Build list of parent items to keep
+ */
+
+ if(isset($keep_element_ids[0])){
+
+ $temp = array($keep_element_ids[0]); // first element is the active menu item
+ $break = false;
+ while(!$break){
+ $break = true;
+ foreach($old_elems as $elm){
+ if(in_array($elm->$id_field, $keep_element_parents) && !in_array($elm->$parent_field, $keep_element_parents)){
+ $keep_element_parents[] = $elm->$parent_field;
+ $break = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Added: 6/3/14
+ * Add elements matching parent id
+ */
+ foreach($old_elems as $elm){
+ if(in_array($elm->$parent_field, $keep_element_parents)){
+ $keep_element_ids[] = $elm->$id_field;
+ }
+ }
+
+ }else{
+ $section_parents = array(0);
+ }
+
+ if($this->show_parent && $this->menu_start > 0){
+ $this->menu_start--;
+ $this->menu_depth++;
+ }
+
+ while($parent_count < count($section_parents)){
+
+ $parent_count = count($section_parents);
+
+ foreach($old_elems as $elm){
+
+ if(in_array($elm->$parent_field, $section_parents) && !in_array($elm->$id_field, $section_parents)){
+ $section_parents[] = $elm->$id_field;
+ $new_elems[] = $elm;
+ }
+ }
+ }
+
+ /**
+ * Added: 6/3/14
+ * Remove elements which are not in $keep_element_ids
+ */
+ foreach($test_elms as $k =>$elm){
+ if(!in_array($elm->$id_field, $keep_element_ids)){
+ unset($test_elms[$k]);
+ }elseif($elm->$parent_field == 0 && (!isset($elm->split_section) || $elm->split_section != 1) && (!isset($elm->current) || $elm->current != 1) && (!isset($elm->current_item_parent) || $elm->current_item_parent != 1) && (!isset($elm->current_item_ancestor) || $elm->current_item_ancestor != 1)){
+ unset($test_elms[$k]);
+ }
+ }
+
+ return $test_elms;
+ }
+
+ public function set_elements_depth($elements, $parent = 0, $menu = false){
+ /**
+ * Set Menu Item Depth
+ */
+ $menu_depths = array();
+ $menu_elements = array();
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+ $counter = 0;
+
+ $depth_field = $menu ? 'menu_depth' : 'depth';
+
+ while(count($menu_elements) < count($elements) && $counter < 5){
+
+ foreach($elements as $k => $e){
+ if($e->$parent_field == $parent){
+
+ if(!isset($menu_depths[0]) || !is_array($menu_depths[0])){
+ $menu_depths[0] = array();
+ }
+
+ // add id to $menu_elements
+ if(!isset($elements[$k]->$depth_field)){
+ $menu_elements[] = $e->$id_field;
+ $menu_depths[0][] = $e->$id_field;
+ $elements[$k]->$depth_field = 0;
+ }
+
+ }else{
+
+ $break = false;
+ foreach($menu_depths as $tax_depth => $parents){
+ foreach($parents as $parent_id){
+
+ if($e->$parent_field == $parent_id){
+
+ if(!isset($menu_depths[$tax_depth+1]) || !is_array($menu_depths[$tax_depth+1])){
+ $menu_depths[$tax_depth+1] = array();
+ }
+
+ // add id to $menu_elements
+ if(!isset($elements[$k]->$depth_field)){
+ $menu_elements[] = $e->$id_field;
+ $menu_depths[$tax_depth+1][] = $e->$id_field;
+ $elements[$k]->$depth_field = $tax_depth+1;
+ }
+
+ $break = true;
+ continue;
+ }
+ }
+
+ if($break)
+ continue;
+ }
+ }
+ }
+ $counter++;
+ }
+
+ return $elements;
+ }
+
+ public function _set_elements_state($elements){
+
+ $parent_field = $this->db_fields['parent'];
+ $id_field = $this->db_fields['id'];
+ $current_item_found = false;
+ $parent_item_found = false;
+ $item_id = 0;
+ $prev_item_id = 0;
+ $break = false;
+
+ while(!$break){
+
+ $break = true;
+
+ foreach($elements as &$element){
+
+ if(!$current_item_found && isset($element->current) && $element->current == 1){
+
+ $current_item_found = true;
+ $item_id = $element->$parent_field;
+ $break = false;
+ $this->selected_section_ids[] = $element->$id_field;
+ $element->split_section = 1;
+ }
+
+ if($current_item_found && $item_id == $element->$id_field){
+
+ $item_id = $element->$parent_field;
+ $element->split_section = 1;
+ $break = false;
+
+ if(!$parent_item_found){
+ $element->classes[] = 'current-menu-parent';
+ $element->current_item_parent = 1;
+ $parent_item_found = true;
+ }
+
+ $element->classes[] = 'current-menu-ancestor';
+ $element->current_item_ancestor = 1;
+ $this->selected_section_ids[] = $element->$id_field;
+ }
+
+ if($current_item_found && $item_id == 0){
+ break;
+ }
+ }
+
+ if($item_id == 0 || $item_id == $prev_item_id){
+ $break = true;
+ }
+
+ $prev_item_id = $item_id;
+ }
+
+ return $elements;
+ }
+
+ /**
+ * Generate Elements from page items
+ * @param stdObj $menu_item Current Menu Item Being Populated
+ * @param array $page_parent_id Page to get children of
+ * @param bool $replace_parent
+ * @return array list of elements
+ */
+ public function _populate_page_items($menu_item, $page_parent_id, $replace_parent = false){
+
+ global $post;
+
+ $elements = array();
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+ $order = SubmenuModel::get_meta($menu_item->$id_field, 'page-order');
+ $orderby = SubmenuModel::get_meta($menu_item->$id_field, 'page-orderby');
+ $exclude = SubmenuModel::get_meta($menu_item->$id_field, 'page-exclude');
+
+ $page_query = array(
+ 'hierarchical' => 1,
+ 'child_of' => $page_parent_id,
+ 'sort_order' => $order,
+ 'sort_column' => $orderby ,
+ 'exclude' => $exclude
+ );
+
+ // apply filters
+ $page_query = apply_filters( 'jcs/page_query_args', $page_query );
+ $page_query = apply_filters('jcs/page_'.$menu_item->$id_field.'_query_args', $page_query );
+
+ // run page query
+ $pages = get_pages($page_query);
+
+ foreach($pages as $p){
+
+ $p->$id_field = $p->ID;
+ $p->object = 'page';
+ $p->object_id = $p->ID;
+
+
+ $p->title = apply_filters( 'jcs/item_title', $p->post_title, $p->ID, 'page' );
+ $p->title = apply_filters( 'jcs/page_item_title', $p->title, $p->ID );
+
+ $p->url = apply_filters( 'jcs/item_url', get_permalink( $p->ID), $p->ID, 'page' );
+ $p->url = apply_filters( 'jcs/page_item_url', $p->url, $p->ID );
+
+ $p->classes = array();
+
+ if($p->post_parent == $page_parent_id){
+
+ // remove childpop item
+ // $p->$parent_field = $menu_item->$id_field;
+ if($replace_parent){
+ $p->$parent_field = $menu_item->$parent_field;
+ }else{
+ $p->$parent_field = $menu_item->$id_field;
+ }
+
+ }else{
+ $p->$parent_field = $p->post_parent;
+ }
+
+ // add classes
+ $p->classes = apply_filters( 'jcs/item_classes', $p->classes, $p->ID, 'page');
+ $p->classes = apply_filters( 'jcs/page_item_classes', $p->classes, $p->ID);
+
+ // check if this page is the current page
+ if( is_page($p->ID) && $post->ID == $p->ID){
+
+ // $current_dynamic_parent = $p->$parent_field;
+ $p->classes[] = 'current-menu-item';
+ $p->split_section = true;
+ $p->current = 1;
+ }
+
+ $elements[] = clone($p);
+ }
+
+ return $elements;
+ }
+
+ /**
+ * Generate Elements of post type
+ * @param stdObj $menu_item Current Menu Item Being Populated
+ * @param array $page_parent_id Post type to populate with
+ * @param bool $replace_parent
+ * @return array list of elements
+ */
+ public function _populate_post_items($menu_item, $post_type, $replace_parent = false){
+ global $post;
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+ $elements = array();
+
+ $limit = SubmenuModel::get_meta($menu_item->$id_field, 'post-limit');
+ $order = SubmenuModel::get_meta($menu_item->$id_field, 'post-order');
+ $orderby = SubmenuModel::get_meta($menu_item->$id_field, 'post-orderby');
+ $post_tax = SubmenuModel::get_meta($menu_item->$id_field, 'post-tax');
+ $post_term = intval(SubmenuModel::get_meta($menu_item->$id_field, 'post-term'));
+
+ $post_query = array(
+ 'post_type' => $post_type,
+ 'posts_per_page' => $limit,
+ 'order' => $order,
+ 'orderby' => $orderby
+ );
+
+ // add taxonomy filter
+ if( !empty($post_tax) && taxonomy_exists( $post_tax ) ){
+ $tax_args = array( 'taxonomy' => $post_tax, 'field' => 'id' );
+
+ if(get_term_by( 'id', $post_term, $post_tax)){
+ $tax_args['terms'] = $post_term;
+ }
+
+ $post_query['tax_query'] = array(
+ $tax_args
+ );
+ }
+
+ // apply filters
+ $post_query = apply_filters( 'jcs/post_query_args', $post_query );
+ $post_query = apply_filters('jcs/post_'.$menu_item->$id_field.'_query_args', $post_query );
+
+ // change id field to parent field
+ if($replace_parent){
+ $id_field = $this->db_fields['parent'];
+ }
+
+ // run post type query
+ $post_type_query = new WP_Query($post_query);
+
+ if($post_type_query->have_posts()){
+ foreach($post_type_query->posts as $p){
+
+ // set menu item variables
+ $p->$id_field = $p->ID;
+ $p->object = 'post';
+ $p->object_id = $p->ID;
+
+ $p->title = apply_filters( 'jcs/item_title', $p->post_title, $p->ID, $post_type );
+ $p->title = apply_filters( 'jcs/post_item_title', $p->title, $p->ID );
+
+ $p->url = apply_filters( 'jcs/item_url', get_permalink( $p->ID), $p->ID, $post_type );
+ $p->url = apply_filters( 'jcs/post_item_url', $p->url, $p->ID );
+
+ $p->$parent_field = $menu_item->$id_field;
+ $p->classes = array();
+
+ if(is_post_type_hierarchical($post_type )){
+
+ if($p->post_parent == $post_type){
+
+ // remove childpop item
+ if($replace_parent){
+ $p->$parent_field = $menu_item->$parent_field;
+ }else{
+ $p->$parent_field = $menu_item->$id_field;
+ }
+
+ }else{
+ $p->$parent_field = $p->post_parent;
+ }
+ }
+
+ // add classes
+ $p->classes = apply_filters( 'jcs/item_classes', $p->classes, $p->ID, $post_type);
+ $p->classes = apply_filters( 'jcs/post_item_classes', $p->classes, $p->ID);
+
+ // check if post item is the current page
+ if(is_single($post) && is_singular( $post_type ) && $post->ID == $p->ID){
+ $p->classes[] = 'current-menu-item';
+ $p->split_section = true;
+ $p->current = 1;
+ }
+
+ $elements[] = clone($p);
+ }
+ }
+
+ return $elements;
+ }
+
+ /**
+ * Generate Elements of taxonomy
+ * @param stdObj $menu_item Current Menu Item Being Populated
+ * @param array $page_parent_id Taxonomy to populate from
+ * @param bool $replace_parent
+ * @return array list of elements
+ */
+ public function _populate_tax_items($menu_item, $taxonomy, $replace_parent = false){
+
+ global $post;
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+
+ $dynamic_item_prefix = str_repeat(0, $this->dynamic_count);
+
+ $tax_parent_id = $menu_item->$id_field;
+
+ $order = SubmenuModel::get_meta($tax_parent_id, 'tax-order');
+ $orderby = SubmenuModel::get_meta($tax_parent_id, 'tax-orderby');
+ $hide = SubmenuModel::get_meta($tax_parent_id, 'tax-empty');
+ $exclude = SubmenuModel::get_meta($tax_parent_id, 'tax-exclude');
+ $tax_max_depth = intval(SubmenuModel::get_meta($tax_parent_id, 'tax-depth'));
+ $tax_term = intval(SubmenuModel::get_meta($tax_parent_id, 'tax-term'));
+
+ $term_query = array(
+ 'hide_empty' => $hide,
+ 'order' => $order,
+ 'orderby' => $orderby,
+ // 'exclude' => $exclude,
+ 'exclude_tree' => $exclude,
+ 'child_of' => $tax_term
+ );
+
+ // apply filters
+ $term_query = apply_filters( 'jcs/term_query_args', $term_query );
+ $term_query = apply_filters('jcs/term_'.$menu_item->$id_field.'_query_args', $term_query );
+
+ // run term query
+ $terms = get_terms( $taxonomy, $term_query );
+
+ $tax_elements = array();
+
+ // change id field to parent field
+
+ foreach($terms as $t){
+ $t->$id_field = $dynamic_item_prefix . $t->term_id;
+ $t->ID = $t->term_id;
+ // $t->db_id = $t->term_id;
+ $t->object = 'term';
+ $t->object_id = $t->term_id;
+
+ $t->title = apply_filters( 'jcs/item_title', $t->name, $t->ID, 'term' );
+ $t->title = apply_filters( 'jcs/term_item_title', $t->title, $t->ID );
+
+ $t->url = apply_filters( 'jcs/item_url', get_term_link( $t, $taxonomy ), $t->ID , 'term');
+ $t->url = apply_filters( 'jcs/term_item_url', $t->url, $t->ID );
+
+ $t->classes = array();
+
+ if($t->parent == 0 || $t->parent == $tax_term){
+
+ // remove childpop item
+ if($replace_parent){
+ $t->$parent_field = $menu_item->$parent_field;
+ }else{
+ $t->$parent_field = $tax_parent_id;
+ }
+
+ }else{
+ $t->$parent_field = $dynamic_item_prefix . $t->parent;
+ }
+
+ // add classes
+ $t->classes = apply_filters( 'jcs/item_classes', $t->classes, $t->ID, 'term');
+ $t->classes = apply_filters( 'jcs/term_item_classes', $t->classes, $t->ID);
+
+ if((is_category() && is_category( $t->ID )) || (is_tag() && is_tag( $t->slug )) || is_tax( $taxonomy, $t->slug ) || ( is_singular() && has_term( $t->term_id, $taxonomy ) ) ){
+ $t->classes[] = 'current-menu-item';
+ $t->split_section = true;
+ $t->current = 1;
+ }
+
+ $tax_elements[] = clone($t);
+ }
+
+ // term depth
+ if($tax_max_depth > 0){
+ $tax_elements = $this->set_elements_depth($tax_elements, $tax_parent_id);
+
+ foreach($tax_elements as $tag_key => $tag_elem){
+
+ if($tag_elem->depth >= $tax_max_depth){
+ unset($tax_elements[$tag_key]);
+ }
+ }
+ }
+
+ $this->dynamic_count++;
+
+ return $tax_elements;
+ }
+
+ /**
+ * Generate Elements from post archive
+ * @param stdObj $menu_item Current Menu Item Being Populated
+ * @param array $page_parent_id Post type to populate with
+ * @param bool $replace_parent
+ * @return array list of elements
+ */
+ public function _populate_archive_items($menu_item, $post_type, $replace_parent = false){
+
+ global $post, $wp;
+
+ $current_url = add_query_arg( $wp->query_string, '', home_url( $wp->request ) );
+ //quickfix
+ if(strpos($current_url, '/?') === false && strpos($current_url, '?') !== false){
+ $current_url = str_replace('?', '/?', $current_url);
+ }
+
+ $id_field = $this->db_fields['id'];
+ $parent_field = $this->db_fields['parent'];
+ $return = wp_get_archives( array('format' => 'custom', 'echo' => false));
+ $test = preg_replace_callback('/(.*?)<\/a>/', array($this, 'extract_archive_month'), $return);
+ $elements = array();
+ $dynamic_item_prefix = str_repeat(0, $this->dynamic_count);
+ $archive_parent_id = $menu_item->$id_field;
+ $group_by_year = SubmenuModel::get_meta($archive_parent_id, 'archive-group');
+
+ $id = 0;
+
+ if(!empty($this->links)){
+
+ $years = array();
+
+ if($group_by_year){
+
+ $this->get_archive_years();
+
+ foreach($this->year_links as $year => $year_data){
+
+ $id++;
+
+ $element = new StdClass();
+ $element->title = $year_data['title'];
+ $element->url = $year_data['url'];
+ $element->$id_field = $dynamic_item_prefix.$id;
+ $element->ID = $dynamic_item_prefix.$id;
+
+ $years[$year] = $dynamic_item_prefix.$id;
+
+ // remove childpop item
+ if($replace_parent){
+ $element->$parent_field = $menu_item->$parent_field;
+ }else{
+ $element->$parent_field = $menu_item->$id_field;
+ }
+
+ if(is_year() && strcasecmp($current_url, $element->url) == 0){
+ $element->current = 1;
+ $element->classes[] = 'current-menu-item';
+ $element->split_section = true;
+ }
+
+ $elements[] = clone($element);
+ }
+ }
+
+ foreach($this->links as $link){
+
+ $id++;
+
+ $element = new StdClass();
+ $element->title = $link['title'];
+ $element->url = $link['url'];
+ $element->$id_field = $dynamic_item_prefix.$id;
+ $element->ID = $dynamic_item_prefix.$id;
+
+ if(array_key_exists($link['year'], $years)){
+
+ $element->$parent_field = $years[$link['year']];
+ }else{
+
+ // remove childpop item
+ if($replace_parent){
+ $element->$parent_field = $menu_item->$parent_field;
+ }else{
+ $element->$parent_field = $menu_item->$id_field;
+ }
+ }
+
+ if((is_month() || is_year()) && strcasecmp($current_url, $element->url) == 0){
+ $element->current = 1;
+ $element->classes[] = 'current-menu-item';
+ $element->split_section = true;
+ }
+
+ $elements[] = clone($element);
+ }
+
+
+ }
+
+ return $elements;
+ }
+
+ public function get_archive_years(){
+ $return = wp_get_archives( array('format' => 'custom', 'echo' => false, 'type' => 'yearly'));
+ $test = preg_replace_callback('/ (.*?)<\/a>/', array($this, 'extract_archive_year'), $return);
+ return $this->year_links;
+ }
+
+ var $links = array();
+ var $year_links = array();
+ var $years = array();
+
+ public function extract_archive_year($data){
+ if(isset($data[1]) && isset($data[2])){
+
+ $year = $data[2];
+
+ // create list of years
+ if(!in_array($year, $this->years)){
+ $this->years[] = $year;
+ }
+
+ $this->year_links[$year] = array('title' => $year, 'url' => $data[1]);
+ }
+ return '';
+ }
+
+ public function extract_archive_month($data){
+ if(isset($data[1]) && isset($data[2])){
+
+ // extract year and month from title
+ $date = explode(' ', $data[2]);
+ $month = $date[0];
+ $year = $date[1];
+
+ $this->links[] = array('title' => $data[2], 'url' => $data[1], 'year' => $year, 'month' => $month);
+ }
+ return '';
+ }
+}
\ No newline at end of file
diff --git a/widgets/SectionMenuWidget.php b/widgets/SectionMenuWidget.php
new file mode 100644
index 0000000..23ca15b
--- /dev/null
+++ b/widgets/SectionMenuWidget.php
@@ -0,0 +1,216 @@
+
+ * @version 0.0.1
+ */
+class JC_Section_Menu_Widget extends WP_Widget {
+
+ /**
+ * Register Widget
+ */
+ public function __construct() {
+ parent::__construct(
+ 'jc_section_menu_widget', // Base ID
+ 'Section Menu Widget', // Name
+ array( 'description' => __( 'JC Submenu Menu Section Widget, display a section of a the current menu.')) // Args
+ );
+ }
+
+ /**
+ * Widget Output
+ * @param array $args
+ * @param array $instance
+ * @return void
+ */
+ public function widget( $args, $instance ) {
+
+ extract( $args );
+
+ $title = apply_filters( 'widget_title', $instance['title'] );
+
+ echo $before_widget;
+
+ if ( ! empty( $title ) )
+ echo $before_title . $title . $after_title;
+
+ do_action('jcs/menu_section', $instance['menu'], array(
+ 'start' => $instance['menu_item'],
+ 'depth' => $instance['menu_depth'],
+ 'show_parent' => $instance['show_parent'],
+ ));
+
+ echo $after_widget;
+ }
+
+ /**
+ * Widget Options
+ * @param array $instance
+ * @return void
+ */
+ public function form( $instance ) {
+
+ $title = isset($instance['title']) ? $instance['title'] : '';
+ $menu = isset($instance['menu']) ? $instance['menu'] : '';
+ $menu_item = isset($instance['menu_item']) ? $instance['menu_item'] : 0;
+ $menu_depth = isset($instance['menu_depth']) ? $instance['menu_depth'] : 1;
+ $show_parent = isset($instance['show_parent']) ? $instance['show_parent'] : 0;
+ $menus = get_terms('nav_menu');
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ checked="checked" />
+ Show Parent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ checked="checked" />
+ Show Parent
+
+
+
+ checked="checked" />
+ Show Hierarchy
+
+
+ * @version 0.0.1
+ */
+class JC_Split_Menu_Widget extends WP_Widget {
+
+ /**
+ * Register Widget
+ */
+ public function __construct() {
+ parent::__construct(
+ 'jc_split_menu_widget', // Base ID
+ 'Split Menu Widget', // Name
+ array( 'description' => __( 'JC Submenu Split Menu Widget, display a section of a the current menu.')) // Args
+ );
+ }
+
+ /**
+ * Widget Output
+ * @param array $args
+ * @param array $instance
+ * @return void
+ */
+ public function widget( $args, $instance ) {
+
+ extract( $args );
+
+ ob_start();
+
+ do_action('jcs/split_menu', $instance['menu'], array(
+ 'hierarchy' => $instance['menu_hierarchy'],
+ 'start' => $instance['menu_start'],
+ 'depth' => $instance['menu_depth'],
+ 'show_parent' => $instance['show_parent'],
+ 'trigger_depth' => $instance['trigger_depth'],
+ ));
+
+ $widget = ob_get_contents();
+ ob_end_clean();
+
+ $title = apply_filters( 'widget_title', $instance['title'] );
+ $title = apply_filters( 'jcs/split_widget_title', $title );
+
+ // hide if no menu items appear
+ if(empty($widget))
+ return;
+
+ echo $before_widget;
+
+ if ( ! empty( $title ) )
+ echo $before_title . $title . $after_title;
+
+ echo $widget;
+
+ echo $after_widget;
+ }
+
+ /**
+ * Widget Options
+ * @param array $instance
+ * @return void
+ */
+ public function form( $instance ) {
+
+ $title = isset($instance['title']) ? $instance['title'] : '';
+ $menu = isset($instance['menu']) ? $instance['menu'] : '';
+ $menu_hierarchy = isset($instance['menu_hierarchy']) ? $instance['menu_hierarchy'] : 1;
+ $show_parent = isset($instance['show_parent']) ? $instance['show_parent'] : 1;
+ $menu_start = isset($instance['menu_start']) ? $instance['menu_start'] : 1;
+ $menu_depth = isset($instance['menu_depth']) ? $instance['menu_depth'] : 5;
+ $trigger_depth = isset($instance['trigger_depth']) ? $instance['trigger_depth'] : 0;
+ $menus = get_terms('nav_menu');
+
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '.$x.'';
+ }
+ ?>
+
+
+
+
+ checked="checked" />
+ Show Parent
+
+
+
+ checked="checked" />
+ Show Hierarchy
+
+