Skip to content

Instantly share code, notes, and snippets.

@sancarn
Last active October 16, 2018 23:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sancarn/68003988e83581f09dbbaa85be6611bd to your computer and use it in GitHub Desktop.
Save sancarn/68003988e83581f09dbbaa85be6611bd to your computer and use it in GitHub Desktop.
Query javascript objects for a specific structure

Object::query()

Say you have some object:

var data = [
  {
    type:"Person",
    name: "Suzanne",
    pets:[
      {
        type:"Cat",
        name:"Charles"
      }
    ],
    children:[
      {
        type:"Person",
        name:"Chelsey",
        pets:[
          {
            type:"Cat",
            name:"Charlotte"
          },{
            type:"Cat",
            name:"Vicky"
          }
        ]
      },{
        type:"Person",
        name:"Drake",
        pets:[
          {
            type:"Dog", name:"Ploddy"
          }
        ]
      }
    ]
  },{
    type:"Person",
    name: "Arun",
    pets:[
      {
        type:"Cat",
        name:"Jackson"
      }
    ]
  }
]

Say that we want to find all People who have Cats as pets. Because of the nested structure of our data it becomes slightly difficult, as children also have pets.

This is where Object.query comes in:

var results = data.query(function(obj){
  return obj.type=="Person" && obj.pets!=undefined && obj.pets.filter((pet)=>pet.type=="Cat").length!=0
})

This will return the following data:

{
  "root.0":{"type":"Person","name":"Suzanne","pets":[{"type":"Cat","name":"Charles"}],"children":[{"type":"Person","name":"Chelsey","pets":[{"type":"Cat","name":"Charlotte"},{"type":"Cat","name":"Vicky"}]},{"type":"Person","name":"Drake","pets":[{"type":"Dog","name":"Ploddy"}]}]},
  "root.0.children.0":{"type":"Person","name":"Chelsey","pets":[{"type":"Cat","name":"Charlotte"},{"type":"Cat","name":"Vicky"}]},
  "root.1":{"type":"Person","name":"Arun","pets":[{"type":"Cat","name":"Jackson"}]}
}

Such that:

Object.values(results).map(function(person){return person.name}) //=>["Suzanne","Chelsey","Arun"]

Ultimately, query provides a quick and easy way to search objects.

It also works for recursive object structures!


You should be able to check for recursive structure with the following condition:

var results = document.body.query((obj)=>obj instanceof Object && obj[Object.seen_symbol])

However this currently doesn't work?

Object.seen_symbol = Symbol("seen")
Object.query = function(obj,fn,options){
//Initialisation:
data = {}
data.root = options.root || "root"
//These variables are important for spotting and handling recursive structures
var seen = Object.seen_symbol
data.seen_objects = [];
//Initialise dataObject array:
data.test_objects = [{key:data.root,value:obj,path:data.root}];
//This object will contain the return objects and paths
data.items = {}
//Loop over all data objects, check each value and loop over all sub-objects.
//Also, ensure recursive structures are caught and handled appropriately.
while(dataObject=data.test_objects.pop()){
//Check if dataObject complies with function
if(fn(dataObject.value,dataObject.key)){
data.items[dataObject.path] = dataObject.value
}
//If dataObject is an object, check all it's sub-objects
if(dataObject.value instanceof Object){
if(!dataObject.value[seen]){
dataObject.value[seen] = true;
data.seen_objects.push(dataObject.value);
//Add all keys to test object list
var keys = Object.keys(dataObject.value);
keys.forEach(function(key){
data.test_objects.push({
key: key,
value: dataObject.value[key],
path: dataObject.path + "." + key
});
});
}
}
}
//Cleanup: Remove seen key
data.seen_objects.forEach(function(obj){
delete obj[seen]
})
//Return items
return data.items
}
Object.prototype.query = function(queryFn,options){
return Object.query(this,queryFn,options)
}

From this json: https://docs.microsoft.com/en-us/office/vba/api/TOC.json

Determine the number (and which classes) have VBA Events.

This can be done with an object query and the following callback:

Object.query(data,function(el){
  if(el.children != undefined)
    return el.children.filter(function(el){
      return el.toc_title == "Events"
    }).length>0
},{root:"data"})

Results:

MsoEnvelope object
CustomXMLParts object
CustomXMLPart object
CustomTaskPane object
CommandBars object
CommandBarComboBox object
CommandBarButton object
Visual Basic for Applications
Visual Basic Add-in Model
Properties
Objects
Microsoft Forms
Document object
Application object
Viewer object
Windows object
Window object
Styles object
Style object
Shape object
Section object
Row object
Pages object
Page object
Masters object
Master object
InvisibleApp object
Documents object
Document object
DataRecordsets object
DataRecordset object
Characters object
Cell object
Application object
Document object
Application object
Project object
Application object
Application object
ToggleButton object
TabStrip object
OptionButton object
MultiPage object
ListBox object
Label object
Image object
Frame object
CommandButton object
ComboBox object reference
CheckBox object reference
Object model (Outlook View control reference)
Views object
TaskRequestUpdateItem object
TaskRequestItem object
TaskRequestDeclineItem object
TaskRequestAcceptItem object
TaskItem object
SyncObject object
Stores object
SharingItem object
Results object
ReportItem object
RemoteItem object
Reminders object
PostItem object
OutlookBarShortcuts object
OutlookBarPane object
OutlookBarGroups object
OlkTimeZoneControl object
OlkTimeControl object
OlkTextBox object
OlkSenderPhoto object
OlkOptionButton object
OlkListBox object
OlkLabel object
OlkInfoBar object
OlkDateControl object
OlkContactPhoto object
OlkCommandButton object
OlkComboBox object
OlkCheckBox object
OlkCategory object
OlkBusinessCardControl object
NavigationPane object
NavigationGroups object
NameSpace object
MeetingItem object
MailItem object
JournalItem object
Items object
Inspectors object
Inspector object
FormRegion object
Folders object
Folder object
Explorers object
Explorer object
DocumentItem object
DistListItem object
ContactItem object
AppointmentItem object
Application object
AccountSelector object
Accounts object
Worksheet object
Workbook object
QueryTable object
OLEObject object
Chart object
Application object
WebBrowserControl object
ToggleButton object
TextBox object
TabControl object
SubForm object
Section object
Report object
References object
Rectangle object
Page object
OptionGroup object
OptionButton object
ObjectFrame object
NavigationControl object
NavigationButton object
ListBox object
Label object
Image object
Form object
CustomControl object
CommandButton object
ComboBox object
CheckBox object
BoundObjectFrame object
Attachment object
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment