{"action":"created","issue":{"url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/101","labels_url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/101/labels{/name}","comments_url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/101/comments","events_url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/101/events","html_url":"https://github.com/jonmiles/bootstrap-treeview/issues/101","id":93932684,"number":101,"title":"Feature Request: New options for search","user":{"login":"gideonapollob","id":7285317,"avatar_url":"https://avatars.githubusercontent.com/u/7285317?v=3","gravatar_id":"","url":"https://api.github.com/users/gideonapollob","html_url":"https://github.com/gideonapollob","followers_url":"https://api.github.com/users/gideonapollob/followers","following_url":"https://api.github.com/users/gideonapollob/following{/other_user}","gists_url":"https://api.github.com/users/gideonapollob/gists{/gist_id}","starred_url":"https://api.github.com/users/gideonapollob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gideonapollob/subscriptions","organizations_url":"https://api.github.com/users/gideonapollob/orgs","repos_url":"https://api.github.com/users/gideonapollob/repos","events_url":"https://api.github.com/users/gideonapollob/events{/privacy}","received_events_url":"https://api.github.com/users/gideonapollob/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-07-09T02:07:48Z","updated_at":"2015-12-04T18:10:16Z","closed_at":null,"body":"Hi. Your treeview is great and its search feature works like a charm... though I want to ask for some new option:\r\n\r\n    $('#tree').treeview('search', [ 'search_filter', {\r\n        ignoreCase: true,     // case insensitive\r\n        exactMatch: false,    // like or equals\r\n        revealResults: true,  // reveal matching nodes\r\n        fadeOutMismatched: true,\r\n        collapse: true\r\n    }]);\r\n\r\na. This requested `fadeOutMismatched` feature/option makes the tree to fade out all non-matching nodes  to the `search_filter` value. Also all ancestor and descendant of a matching node will be excluded on fade out.\r\n\r\nb. The requested `collapse` feature/option makes the tree to collapse all node and reveal the node that matches the `search_filter` string.\r\n\r\n I believe this feature will come handy on scenarios having a tree more than 100 nodes with subnodes. Thanks in advance."},"comment":{"url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/comments/162038075","html_url":"https://github.com/jonmiles/bootstrap-treeview/issues/101#issuecomment-162038075","issue_url":"https://api.github.com/repos/jonmiles/bootstrap-treeview/issues/101","id":162038075,"user":{"login":"ypnos-web","id":15981753,"avatar_url":"https://avatars.githubusercontent.com/u/15981753?v=3","gravatar_id":"","url":"https://api.github.com/users/ypnos-web","html_url":"https://github.com/ypnos-web","followers_url":"https://api.github.com/users/ypnos-web/followers","following_url":"https://api.github.com/users/ypnos-web/following{/other_user}","gists_url":"https://api.github.com/users/ypnos-web/gists{/gist_id}","starred_url":"https://api.github.com/users/ypnos-web/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ypnos-web/subscriptions","organizations_url":"https://api.github.com/users/ypnos-web/orgs","repos_url":"https://api.github.com/users/ypnos-web/repos","events_url":"https://api.github.com/users/ypnos-web/events{/privacy}","received_events_url":"https://api.github.com/users/ypnos-web/received_events","type":"User","site_admin":false},"created_at":"2015-12-04T18:10:16Z","updated_at":"2015-12-04T18:10:16Z","body":"Here is some javascript code that implements a variant of this based on current bootstrap-treeview master (no need to alter bootstrap-treeview code). It uses 'disabled' state to hide nodes. CSS:\r\n````css\r\n#example-tree .node-disabled {\r\n    display: none;\r\n}\r\n````\r\n\r\nThen, all nodes that are not relevant to the search results are disabled.\r\nAlso, at the beginning of each search, the whole tree is collapsed. So in the end, only nodes are shown that are parents of search results or search results, and also these are fully expanded.\r\n\r\n````javascript\r\n$(function () {\r\n    var selectors = {\r\n        'tree': '#example-tree',\r\n        'input': '#example-search',\r\n        'reset': '#example-reset'\r\n    };\r\n    var lastPattern = ''; // closure variable to prevent redundant operation\r\n\r\n    /* collapse and enable all before search */\r\n    function reset(tree) {\r\n        tree.collapseAll();\r\n        tree.enableAll();\r\n    }\r\n\r\n    /* find all nodes that are not related to search and should be disabled:\r\n     * This excludes found nodes, their children and their parents.\r\n     * Call this after collapsing all nodes and letting search() reveal.\r\n     */\r\n    function collectUnrelated(nodes) {\r\n        var unrelated = [];\r\n        $.each(nodes, function (i, n) {\r\n            if (!n.searchResult && !n.state.expanded) { // no hit, no parent\r\n                unrelated.push(n.nodeId);\r\n            }\r\n            if (!n.searchResult && n.nodes) { // recurse for non-result children\r\n                $.merge(unrelated, collectUnrelated(n.nodes));\r\n            }\r\n        });\r\n        return unrelated;\r\n    }\r\n\r\n    /* search callback */\r\n    var search = function (e) {\r\n        var pattern = $(selectors.input).val();\r\n        if (pattern === lastPattern) {\r\n            return;\r\n        }\r\n        lastPattern = pattern;\r\n        var tree = $(selectors.tree).treeview(true);\r\n        reset(tree);\r\n        if (pattern.length < 3) { // avoid heavy operation\r\n            tree.clearSearch();\r\n        } else {\r\n            tree.search(pattern);\r\n            /* get all root nodes: node 0 who is assumed to be\r\n               a root node, and all siblings of node 0. */\r\n            var roots = tree.getSiblings(0);\r\n            roots.push(tree.getNode(0));\r\n            /* first collect all nodes to disable, then call disable once.\r\n               Calling disable on each of them directly is extremely slow! */\r\n            var unrelated = collectUnrelated(roots);\r\n            tree.disableNode(unrelated, {silent: true});\r\n        }\r\n    };\r\n\r\n    /* typing in search field */\r\n    $(selectors.input).on('keyup', search);\r\n\r\n    /* clear button */\r\n    $(selectors.reset).on('click', function (e) {\r\n        $(selectors.input).val('');\r\n        var tree = $(selectors.tree).treeview(true);\r\n        reset(tree);\r\n        tree.clearSearch();\r\n    });\r\n});\r\n````"}}