Plugin Directory

Changeset 1555006


Ignore:
Timestamp:
12/14/2016 10:02:38 PM (9 years ago)
Author:
fifthestate
Message:

Category selector works with new backend

Location:
fifthestate/trunk
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • fifthestate/trunk/js/category-helper.js

    r1555005 r1555006  
    1 document.addEventListener('DOMContentLoaded', function () {
    2     if (document.getElementById('category_tree') != null) {
    3         var categoryTree = document.getElementById('category_tree').innerText;
    4         categoryTree = '{"root": ' + categoryTree + '}';
    5         var categories = JSON.parse(categoryTree)['root'];
    6         var dropdownsRoot = document.getElementsByClassName('category-dropdowns')[0];
     1(function($) {
     2'use strict';
    73
    8         var refreshCategoryDropdowns = function () {
    9             dropdownsRoot.innerHTML = '';
    10             createDropdownsFromCategories('root', categories, []);
    11             selectFromCategories(categories, null);
    12         };
     4var categories, countryData, categoryMap, MAX_CATEGORY_LEVELS = 5;
    135
    14         var createDropdownsFromCategories = function (parentId, categories, path) {
    15             path.push(parentId);
    16             var level = path.length;
    17             if (level <= 5) {
    18                 if (categories.length > 0) {
    19                     var sElem = document.createElement('select');
    20                     sElem.className = 'cat-' + parentId;
    21                     sElem.name = 'cat-' + parentId;
    22                     sElem.onchange = function (event) {
    23                         var selectedCat;
    24                         for (var i = 0; i < categories.length; i++) {
    25                             cat = categories[i];
    26                             if (cat._id === event.target.value) {
    27                                 selectedCat = cat;
    28                                 break;
    29                             }
    30                         }
    31                         if (!selectedCat) {
    32                             console.warn('Could not find category ' + event.target.value + ' in categories of ' + parentId);
    33                             selectedCat = categories[0];
    34                         }
     6$.fn.categorySelector = function(categoriesEndpoint, countryDataEndpoint, currentCategoryId) {
     7    this.html('<input type=hidden name="category_id">');
     8    var elem = this.get(0);
     9    $.when(
     10        $.get(categoriesEndpoint),
     11        $.get(countryDataEndpoint)
     12    ).then(function(categoriesRes, countryDataRes) {
     13        categories = categoriesRes[0];
     14        countryData = countryDataRes[0];
     15        categoryMap = {};
    3516
    36                         if (selectedCat.subcategories.length <= 0) {
    37                             selectCategory(selectedCat);
    38                         } else {
    39                             var successfullySelected = selectFromCategories(selectedCat.subcategories);
    40                             if (!successfullySelected) {
    41                                 selectCategory(selectedCat);
    42                             }
    43                         }
    44                     };
    45                     dropdownsRoot.appendChild(sElem);
    46                     for (var i = 0; i < categories.length; i++) {
    47                         var cat = categories[i];
    48                         [cat.selectElem, cat.path] = createDropdownsFromCategories(cat._id, cat.subcategories, path.slice());
    49                         var option = new Option(cat.name, cat._id);
    50                         sElem.options.add(option);
    51                         cat.optionElem = option;
     17        function formatDict(template, fmt) {
     18            // NOTE: This part differs from the backend and feels hackier to me
     19            //       but is based on http://stackoverflow.com/a/5344074/1796894
     20            var templStr = JSON.stringify(template);
     21            for(var prop in fmt) {
     22                if(fmt.hasOwnProperty(prop)) {
     23                    templStr = templStr.replace(new RegExp('{'+prop+'}', 'g'), fmt[prop]);
     24                }
     25            }
     26            return JSON.parse(templStr, fmt);
     27        }
     28
     29        function prepareWorldCategory(worldCat) {
     30            worldCat.subcategories = [];
     31            for(var continent of countryData.continents) {
     32                var continentCat = formatDict(worldCat.continent_template, continent);
     33                continentCat.subcategories = []
     34                for(var country of continent.countries) {
     35                    continentCat.subcategories.push(formatDict(worldCat.country_template, country))
     36                }
     37                worldCat.subcategories.push(continentCat);
     38            }
     39        }
     40
     41        function walker(categories, parent) {
     42            for(var cat of categories) {
     43                cat.parent = parent;
     44                categoryMap[cat._id] = cat;
     45                if(cat.type === 'world') {
     46                    // TODO: I am writing this twice QQ
     47                    //       See categories.py on the backend
     48                    prepareWorldCategory(cat);
     49                }
     50                walker(cat.subcategories, cat);
     51            }
     52        }
     53        walker(categories);
     54    }, function(err) {
     55        console.error(err);
     56    }).then(function() {
     57        createDropdownsFromCategories(elem, 'root', categories);
     58        selectFromCategories(elem, categories, currentCategoryId);
     59    });
     60
     61    return this;
     62};
     63
     64function createDropdownsFromCategories(dropdownsRoot, parentId, categories, path) {
     65    if(path == null) path = [];
     66    path.push(parentId);
     67    var level = path.length;
     68    if(level <= MAX_CATEGORY_LEVELS) {
     69        if(categories.length > 0) {
     70            var sElem = document.createElement("select");
     71            sElem.className = 'cat-'+parentId;
     72            sElem.onchange = function(event) {
     73                var selectedCat;
     74                for(var cat of categories) {
     75                    if(cat._id === event.target.value) {
     76                        selectedCat = cat;
     77                        break;
    5278                    }
    53                     return [sElem, path];
    5479                }
    55             } else {
    56                 console.warn('List for ' + parentId + ' found at level ' + level + 'which is too deep');
    57             }
    58             return [null, path];
    59         };
     80                if(!selectedCat) {
     81                    console.warn('Could not find category '+event.target.value+' in categories of '+parentId);
     82                    selectedCat = categories[0];
     83                }
    6084
    61         var selectFromCategories = function (categories, selectedCategoryId = null) {
    62             var firstSelectableCategory,
    63                 foundSelectedCategory = false;
    64 
    65             var walker = function (categories, level = 1) {
    66                 if (foundSelectedCategory) {
    67                     return;
    68                 }
    69                 if (level <= 5) {
    70                     for (var i = 0; i < categories.length; i++) {
    71                         cat = categories[i];
    72                         walker(cat.subcategories, level + 1)
    73                         if (cat.subcategories.length <= 0) {
    74                             if (!firstSelectableCategory) {
    75                                 firstSelectableCategory = cat;
    76                             }
    77                             if (selectedCategoryId && selectedCategoryId === cat._id) {
    78                                 foundSelectedCategory = true;
    79                                 selectCategory(cat);
    80                                 break;
    81                             }
    82                         }
     85                if(selectedCat.subcategories.length <= 0) {
     86                    selectCategory(dropdownsRoot, selectedCat);
     87                } else if(selectedCat.subcategories.length > 0) {
     88                    var successfullySelected = selectFromCategories(dropdownsRoot, selectedCat.subcategories);
     89                    if(!successfullySelected) {
     90                        selectCategory(dropdownsRoot, selectedCat);
    8391                    }
    8492                } else {
    85                     console.warn('List found at level ' + level + ' which is too deep.');
     93                    console.error(selectedCat.name+' selected somehow?');
    8694                }
    8795            };
    88             walker(categories);
     96            dropdownsRoot.appendChild(sElem);
     97            for(var cat of categories) {
     98                [cat.selectElem, cat.path] = createDropdownsFromCategories(dropdownsRoot, cat._id, cat.subcategories, path.slice());
     99                var option = new Option(cat.name, cat._id);
     100                sElem.options.add(option);
     101                cat.optionElem = option;
     102            }
     103            return [sElem, path];
     104        }
     105    } else {
     106        console.warn('List for '+parentId+' found at level '+level+' which is too deep');
     107    }
     108    return [null, path];
     109};
    89110
    90             if (!foundSelectedCategory) {
    91                 if (firstSelectableCategory) {
    92                     selectCategory(firstSelectableCategory);
    93                 } else {
    94                     return false;
     111function selectFromCategories(dropdownsRoot, categories, selectedCategoryId) {
     112    var firstSelectableCategory,
     113        foundSelectedCategory = false;
     114
     115    function walker(categories, level = 1) {
     116        if(foundSelectedCategory) return;
     117        if(level <= MAX_CATEGORY_LEVELS) {
     118            for(var cat of categories) {
     119                walker(cat.subcategories, level + 1);
     120                if(cat.subcategories.length <= 0) {
     121                    if(!firstSelectableCategory) {
     122                        firstSelectableCategory = cat;
     123                    }
     124                    if(selectedCategoryId && selectedCategoryId === cat._id) {
     125                        foundSelectedCategory = true;
     126                        selectCategory(dropdownsRoot, cat);
     127                        break;
     128                    }
    95129                }
    96130            }
    97             return true;
    98         };
     131        } else {
     132            console.warn('List found at level '+level+' which is too deep');
     133        }
     134    };
     135    walker(categories);
    99136
    100         var selectCategory = function (category) {
    101             var path = category.path;
    102             for (var i = 0; i < dropdownsRoot.children.length; i++) {
    103                 var dropdown = dropdownsRoot.children[i];
    104                 if (path.some(function (id) {
    105                         return 'cat-' + id === dropdown.className;
    106                     })) {
    107                     dropdown.style.display = 'inline-block';
    108                 } else {
    109                     dropdown.style.display = 'none';
    110                 }
    111             }
    112             for (var i = 0; i < path.length; i++) {
    113                 var id = path[i];
    114                 parentDropdownSearchLoop:
    115                     for (var j = 0; j < dropdownsRoot.children.length; j++) {
    116                         var dropdown = dropdownsRoot.children[j];
    117                         for (var k = 0; k < dropdown.options.length; k++) {
    118                             var option = dropdown.options[k];
    119                             if (option.value === id) {
    120                                 option.selected = true;
    121                                 break parentDropdownSearchLoop;
    122                             }
    123                         }
    124                     }
    125             }
    126         };
    127 
    128         refreshCategoryDropdowns();
     137    if(!foundSelectedCategory) {
     138        if(firstSelectableCategory) {
     139            selectCategory(dropdownsRoot, firstSelectableCategory);
     140        } else {
     141            return false;
     142        }
    129143    }
    130 }, false);
     144    return true;
     145};
    131146
    132147
     148function selectCategory(dropdownsRoot, category) {
     149    // NOTE: this feels kind of kludgy, but...
     150    // http://stackoverflow.com/a/17958847/1796894
     151    // TODO: Generalize this??
     152    // $timeout(() => { this.categoryId = category._id; });
     153
     154    var path = category.path;
     155
     156    Array.from(dropdownsRoot.children).forEach(function(dropdown) {
     157        if(path.some(function(id) { return 'cat-'+id === dropdown.className; })) {
     158            dropdown.style.display = 'inline-block';
     159        } else {
     160            dropdown.style.display = 'none';
     161        }
     162    });
     163
     164    for(var id of path) {
     165        parentDropdownSearchLoop:
     166        Array.from(dropdownsRoot.children).forEach(function(node) {
     167            if(node.nodeName === 'INPUT') {
     168                node.value = category._id;
     169            } else if(node.nodeName === 'SELECT') {
     170                Array.from(node.options).forEach(function(option) {
     171                    if(option.value === id) {
     172                        option.selected = true;
     173                    }
     174                });
     175            }
     176        });
     177    }
     178};
     179
     180}(jQuery));
  • fifthestate/trunk/settings.php

    r1554943 r1555006  
    9191function handle_update_form() {
    9292    $app_state = get_option('fifthestate');
    93     //do stuff to update category
    94     $category = $_POST['cat-root'];
    95     while ( isset( $_POST['cat-'.$category] ) ) {
    96         $category = $_POST['cat-'.$category];
    97     }
    98 
    99     $app_state['category'] = $category;
     93    $app_state['category'] = $_POST['category_id'];
    10094    update_option( 'fifthestate', $app_state );
    10195}
     
    167161    $category_tree = curl_get( SITE_URL . '/data/categories.json', '' );
    168162    ?>
    169     <div id="category_tree" style="display:none"><?php echo $category_tree ?></div>
     163    <!-- <div id="category_tree" style="display:none"><?php echo $category_tree ?></div> -->
    170164    <form method="post" action="">
    171165        <?php
     
    173167        <table class="form-table">
    174168            <tr>
    175                 <th scope="row"><label for="default_category"><?php _e( 'Change Category' ) ?></label></th>
     169                <th scope="row"><label><?php _e( 'Change Category' ) ?></label></th>
    176170                <td>
    177                     <span class="category-dropdowns">
    178 
    179                     </span>
     171                    <span class="category-dropdowns"></span>
     172                </td>
     173                <td>
    180174                    <input type="submit" name="update_category" class="button button-primary" value="Update" />
    181175                </td>
     
    186180        </p>
    187181    </form>
     182    <script>
     183        jQuery('.category-dropdowns').categorySelector('<?=SITE_URL?>/data/categories.json', '<?=SITE_URL?>/data/country_data.json', '<?=$category?>');
     184    </script>
    188185<?php
    189186}
     
    191188//enqueues style and script
    192189add_action( 'admin_enqueue_scripts', function() {
    193     wp_enqueue_script( 'script', plugins_url( 'js/script.js', __FILE__ ), array(), '0.0.0' );
     190    wp_enqueue_script( 'script', plugins_url( 'js/category-helper.js', __FILE__ ), array(), '0.0.0' );
    194191} );
    195192
Note: See TracChangeset for help on using the changeset viewer.