From b98610e58aaa316105695193d57f7108034ce6ca Mon Sep 17 00:00:00 2001 From: lenovo Date: Wed, 16 Nov 2022 21:36:56 +0100 Subject: [PATCH] filters intersection almost works, except remove checkbox action --- :w | 295 ++++++++++++++++++ .../map_prof/scripts/mp_filter_events.js | 153 ++++++--- .../map_prof/srcs/map/mp_create_div.php | 8 +- 3 files changed, 409 insertions(+), 47 deletions(-) create mode 100644 :w diff --git a/:w b/:w new file mode 100644 index 0000000..ccb8d7f --- /dev/null +++ b/:w @@ -0,0 +1,295 @@ + +// https://googlemaps.github.io/js-markerclusterer/classes/MarkerClusterer.html +// add true for noDraw +// bounds : https://stackoverflow.com/questions/19304574/center-set-zoom-of-map-to-cover-all-visible-markers/19304625#19304625 + + + +function array_first_not_in_second(first, second) { + let temp_array = []; + for (let index of first) { + if (second.indexOf(index) == -1) { + temp_array.push(index); + } + } + return temp_array; +} + +function filter_selection_indexes(menu, indexes, reverse, add) { + + if (indexes.length === 0) { + // if array of index is empty, delete menu + delete g_indexes[menu]; + } + else if (reverse) { + // if reverse is true, delete all indexes in g_indexes.menu + // https://stackoverflow.com/questions/5113374/javascript-check-if-variable-exists-is-defined-initialized + if ( typeof(g_indexes[menu]) !== "undefined" && g_indexes[menu] !== null ) { + // creates an array with all values of g_indexes[menu] minus indexes + let temp_array = array_first_not_in_second(g_indexes[menu], indexes); + if (temp_array.length === 0) + delete g_indexes[menu]; + else + g_indexes[menu] = [].concat(temp_array); + } + } + else { + if (add && typeof(g_indexes[menu]) !== "undefined") { + // add array of menus to g_indexes{} + // creates an array with all values of indexes that are not in g_indexes[menu] already + let temp_array = array_first_not_in_second(indexes, g_indexes[menu]); + g_indexes[menu] = g_indexes[menu].concat(temp_array); + } + else { + // replace or create array of menu in g_indexes{} + g_indexes[menu] = [].concat(indexes); + } + } + + // loop through all arrays of g_indexes to find intersection + // take first one as comparison + let keys = Object.keys(g_indexes); + let intersection = []; + let compare = []; + keys.forEach((key, i) => { + if (i == 0) { + intersection = g_indexes[key]; + } + else { + let temp = []; + compare = g_indexes[key]; + for (let index of intersection) { + if (compare.indexOf(index) != -1) + temp.push(index); + } + intersection = [].concat(temp); + } + }); + return intersection; +} + +function redraw_clusters(indexes) { + + let indexes_count = indexes.length; + + if (indexes_count !== 0) { + // if index array, hide all other markers, and if zoomin, zoom to new markers + g_marker_cluster.clearMarkers(true); + + let marker = g_markers[0]; + let current_bounds = g_map.getBounds(); + let bounds = new google.maps.LatLngBounds(); + + let outside_bounds = false; + for (let index of indexes) { + marker = g_markers[index]; + position = marker.getPosition(); + if (! current_bounds.contains(position)) + outside_bounds = true; + bounds.extend(position); + + g_marker_cluster.addMarker(marker, true); + } + if (outside_bounds) { + if (indexes_count === 1) { + g_map.setCenter(position); + g_map.setZoom(max_zoom); + } + else if (indexes_count > 1) { + g_map.fitBounds(bounds); + } + } + + } + else if ( Object.keys(g_indexes).length === 0 ) { + // object is empty, there are no filters + g_map.setCenter(coordinates_default); + g_map.setZoom(2); + g_marker_cluster.addMarkers(g_markers, true); + } + else { + // filters intersection lets no markers on the map + g_marker_cluster.clearMarkers(true); + } + + g_marker_cluster.render(); +} + +/* + should iterate through all dom elements with class "menu_items" + and invert (if exist, suppress, else create) the class construct like this : + disabled_by_menu-name + where menu-name is not the name of the menu that contains the item, + but the name of the menu within wich the click provide. exemple : + - you click on menu-item:"france" in menu:"country" + - it disable menu-item:"conference-table-ronde" in menu:"category" + - by adding class "disabled_by_country" + + - and if you click again on menu-item:"france" in menu:"country" + - it will remove class "disabled_by_country" + - if it's the last class containing "disabled_by_" it will be re-enabled + see css attribute selectors : https://www.w3schools.com/css/css_attribute_selectors.asp +*/ + +function toggle_one_class(menu_from, menu_name, menu_item) { +/* +*/ + console.log("\n" + menu_name + " from " + menu_from + ":"); + console.log("- " + menu_item); + + let html_id = `filter_${menu_name}_${menu_item}`; + let html_class = `disabled_by_${menu_from}`; + + let item = document.getElementById(html_id); + let item_classes = item.classList; + item_classes.toggle(html_class); +} + +function toggle_all_classes() { +/* +*/ + // loop through all items elements of menu in html, and toggle "disabled" if there is or not a class "disabled_by_*" + // get all elements in all menus + let items = document.getElementsByClassName("filter_menu_item"); + + for (let item of items) { + let item_classes = item.classList; + let item_classes_value = item_classes.value; + if ( item_classes_value.includes("disabled_by_") ) + item.setAttribute('disabled', ''); + else + item.removeAttribute('disabled'); + } +} +/* + ' pays ' '-- categories --' + ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' '-- forums --' + ' benin ' '-- seminaire. --' + ' rencontre. ' + ' autres ' + + + ' [pays ] ' ' categories ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + '-- pays --' ' categories ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + '-- bresil --' ' [atelier ] ' + '-- canada --' ' forums ' + '-- benin --' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + ' pays ' ' [categories] ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + ' pays ' '-- categories --' + ' france ' '-- table ron. --' + ' [chili ] ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' '-- seminaire. --' + '-- rencontre. --' + ' autres ' + + + ' pays ' '-- categories --' + ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' '-- forums --' + ' benin ' '-- seminaire. --' + ' rencontre. ' + ' autres ' + + + '-- pays --' '-- categories --' / ' pays ' '-- categories --' + ' france ' ' table ron. ' / ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' / ' chili ' '-- conferenc. --' + '-- bresil --' ' [atelier ] ' / ' bresil ' ' [atelier ] ' + '-- canada --' '-- forums --' / ' canada ' '-- forums --' + '-- benin --' '-- seminaire. --' / ' benin ' '-- seminaire. --' + ' rencontre. ' / ' rencontre. ' + ' autres ' / ' autres ' + +*/ + +function disable_menus(menu_name_ori, menu_item_ori) { + let keys = Object.keys(menu_item_ori); + // loop through list of other menu_items available for this menu_item + // loop though menu names (pays, categories, mode) + for (let menu_name of keys) { + if (menu_name === "_name") + continue; + if (menu_name === "indexes") + continue; + // loop through items in menu names (ex. for "pays" : france, chili, cuba) + for (let item of menu_item_ori[menu_name]) { + toggle_one_class( menu_name_ori, menu_name, item.replace(/ /g, "_") ); + } + } + toggle_all_classes(); + +/* +*/ +} + +function filter_show_only(element, menu_name) { + + g_infowindow.close(); + + let menu_index = element.getAttribute("data-menu_index"); + let menu_item = filters[menu_name][menu_index]; + let indexes = []; + if (menu_index != "menu_name") + indexes = menu_item.indexes; + + add = false; + reverse = false; + if (element.type === "checkbox") { + reverse = ! element.checked; + add = true; + } + + disable_menus(menu_name, menu_item); + + let index_array = filter_selection_indexes(menu_name, indexes, reverse, add); + + redraw_clusters(index_array); +} + + + +function filter_show_all() { + + g_infowindow.close(); + + g_indexes = {}; + g_marker_cluster.clearMarkers(true); + g_marker_cluster.addMarkers(g_markers); + /* dont use fitBounds because it's not well centered */ + /* instead use setCenter and setZoom */ + //g_map.fitBounds(g__init_bounds); + g_map.setCenter(coordinates_default); + g_map.setZoom(2); +} + diff --git a/srcs/plugins/map_prof/scripts/mp_filter_events.js b/srcs/plugins/map_prof/scripts/mp_filter_events.js index d4c9c0a..2b62433 100644 --- a/srcs/plugins/map_prof/scripts/mp_filter_events.js +++ b/srcs/plugins/map_prof/scripts/mp_filter_events.js @@ -116,53 +116,106 @@ function redraw_clusters(indexes) { } /* - should iterate through all dom elements with class "menu_items" - and invert (if exist, suppress, else create) the class construct like this : - disabled_by_menu-name - where menu-name is not the name of the menu that contains the item, - but the name of the menu within wich the click provide. exemple : - - you click on menu-item:"france" in menu:"country" - - it disable menu-item:"conference-table-ronde" in menu:"category" - - by adding class "disabled_by_country" - - and if you click again on menu-item:"france" in menu:"country" - - it will remove class "disabled_by_country" - - if it's the last class containing "disabled_by_" it will be re-enabled - see css attribute selectors : https://www.w3schools.com/css/css_attribute_selectors.asp + ' pays ' '-- categories --' + ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' '-- forums --' + ' benin ' '-- seminaire. --' + ' rencontre. ' + ' autres ' + + + ' [pays ] ' ' categories ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + '-- pays --' ' categories ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + '-- bresil --' ' [atelier ] ' + '-- canada --' ' forums ' + '-- benin --' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + ' pays ' ' [categories] ' + ' france ' ' table ron. ' + ' chili ' ' conferenc. ' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' ' seminaire. ' + ' rencontre. ' + ' autres ' + + + ' pays ' '-- categories --' + ' france ' '-- table ron. --' + ' [chili ] ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' ' forums ' + ' benin ' '-- seminaire. --' + '-- rencontre. --' + ' autres ' + + + ' pays ' '-- categories --' + ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' + ' bresil ' ' atelier ' + ' canada ' '-- forums --' + ' benin ' '-- seminaire. --' + ' rencontre. ' + ' autres ' + + + ' pays ' '-- categories --' + ' [france] ' ' table ron. ' + ' chili ' '-- conferenc. --' + ' bresil ' ' [atelier ] ' + ' canada ' '-- forums --' + ' benin ' '-- seminaire. --' + ' rencontre. ' + ' autres ' + */ -function toggle_one_class(menu_from, menu_name, menu_item) { -/* -*/ - console.log("\n" + menu_name + " from " + menu_from + ":"); - console.log("- " + menu_item); - - let html_id = `filter_${menu_name}_${menu_item}`; - let html_class = `disabled_by_${menu_from}`; - - let item = document.getElementById(html_id); - let item_classes = item.classList; - item_classes.toggle(html_class); +function html_item(menu_name, menu_item) { + let item = menu_item.replace(/ /g, "_"); + let html_id = `filter_${menu_name}_${item}`; + return document.getElementById(html_id); } -function toggle_all_classes() { -/* -*/ - // loop through all items elements of menu in html, and toggle "disabled" if there is or not a class "disabled_by_*" - // get all elements in all menus - let items = document.getElementsByClassName("filter_menu_item"); +function toggle_menu_items(menu_name, x_abled) { + + let name = menu_name.replace(/ /g, "_"); + let class_name = `filter_menu_${name}`; + let items = document.getElementsByClassName(class_name); for (let item of items) { - let item_classes = item.classList; - let item_classes_value = item_classes.value; - if ( item_classes_value.includes("disabled_by_") ) + item.classList.remove('enable'); + if (x_abled === "disable") { item.setAttribute('disabled', ''); - else + } + else { item.removeAttribute('disabled'); + } } } -function disable_menus(menu_name_ori, menu_item_ori) { +function disable_menus(menu_name_ori, menu_item_ori, is_menu_title) { + let menu_item_name = menu_item_ori._name; + let item_ori_html = html_item(menu_name_ori, menu_item_name); + let is_enabled = item_ori_html.classList.contains('enable'); + let keys = Object.keys(menu_item_ori); // loop through list of other menu_items available for this menu_item // loop though menu names (pays, categories, mode) @@ -171,15 +224,21 @@ function disable_menus(menu_name_ori, menu_item_ori) { continue; if (menu_name === "indexes") continue; - // loop through items in menu names (ex. for "pays" : france, chili, cuba) - for (let item of menu_item_ori[menu_name]) { - toggle_one_class( menu_name_ori, menu_name, item.replace(/ /g, "_") ); + if (is_menu_title) { + // true == enable + toggle_menu_items(menu_name, "enable"); + } + else if (! is_enabled) { + // false == disable + toggle_menu_items(menu_name, "disable"); + // loop through items in menu names (ex. for "pays" : france, chili, cuba) + for (let item of menu_item_ori[menu_name]) { + let item_html = html_item(menu_name, item); + item_html.classList.add('enable'); + item_html.removeAttribute('disabled'); + } } } - toggle_all_classes(); - -/* -*/ } function filter_show_only(element, menu_name) { @@ -188,9 +247,12 @@ function filter_show_only(element, menu_name) { let menu_index = element.getAttribute("data-menu_index"); let menu_item = filters[menu_name][menu_index]; + let is_menu_title = true; let indexes = []; - if (menu_index != "menu_name") + if (menu_index != "menu_name") { + is_menu_title = false; indexes = menu_item.indexes; + } add = false; reverse = false; @@ -199,7 +261,7 @@ function filter_show_only(element, menu_name) { add = true; } - disable_menus(menu_name, menu_item); + disable_menus(menu_name, menu_item, is_menu_title); let index_array = filter_selection_indexes(menu_name, indexes, reverse, add); @@ -212,6 +274,9 @@ function filter_show_all() { g_infowindow.close(); + // "item" as a menu name will select all items in all menus + toggle_menu_items("item", "enable"); + g_indexes = {}; g_marker_cluster.clearMarkers(true); g_marker_cluster.addMarkers(g_markers); diff --git a/srcs/plugins/map_prof/srcs/map/mp_create_div.php b/srcs/plugins/map_prof/srcs/map/mp_create_div.php index 6bdbbce..e61bda4 100644 --- a/srcs/plugins/map_prof/srcs/map/mp_create_div.php +++ b/srcs/plugins/map_prof/srcs/map/mp_create_div.php @@ -11,6 +11,7 @@ function mp_filter_drop_down($key, &$filter) { onchange="filter_show_only_selection(this, '.json_encode(array()).', '."'".$key."'".')" onchange="filter_event(this, this.options[this.selectedIndex], \''.$key.'\')" */ + $menu_name_class = 'filter_menu_'.str_replace(" ", "_", $key).''; $content = '