SLB: Notes – JS: Component References

By Sol in Lab

Requirements

  • Unified way to get/set component references from within other components
    • Used as base of other get/set methods (get_viewer(), etc.)
  • Smart – not too dependent on configuration
  • Safe – manages component data without risk of corruption

Get component reference (Process)

Arguments

  • Property name (string): Name of property to retrieve (group, viewer, etc.)
  • Data type (Component Class [function]): Component type (View.Viewer, View.Group, etc.)
    • Validates data type before returning data
    • Enables creation of new component instance if necessary
  • Get default (optional) (boolean): Whether to get default component reference from controller
    • Default: Yes
    • Useful when searching through container components for reference (as returning default reference will stop iteration through containers)

Prioritized search for component

  1. Check if instance property already set
    • Can be set by various operations
      • Previous property retrieval (caches property for future access)
      • Direct property setting (e.g. set_viewer(), etc.)
    • Return value immediately if property is set
  2. Check instance attributes for component
    • Instance attributes stored as: instance.attributes (object)
    • Attribute key matches property name: instance.attributes.viewer will contain viewer reference
    • Possible return values – Dependent on how attribute was set
      • String: ID of component reference
        • Components stored by ID in controller (View)
      • Object reference: Direct reference to another component
    • Set attribute value to main instance property if found (for faster future retrievals)
      • set_component(property_name, value)
        • Sanitizes value
        • Retrieves actual component reference from controller based on ID (string) and component type
  3. Check containers
    • Containers: Component instances that current component instance can inherit/access properties from
      • Such components contain current component (e.g. Group contains Item, etc.)
    • Containers defined in component class definitions (object)
      • Key: property name (group, viewer, etc.)
      • Value: Component data type (View.Group, View.Viewer, etc.)
    • Iterate through containers
      • Retrieve container component reference
        //Example (Group)
        var container = get_component('group', View.Group);
        • - Recursion issue in get_component() if using get_component()to retrieve containers
          • Example: Property being searched for = Container being searched
            • Property: group
            • Current container: group
          • A: Skip containers that match current property being searched for
            • e.g. Don’t look in ‘group’ container if attempting to retrieve ‘group’ reference
      • Look for component reference in valid containers
        var component = container.get_component(property_name, data_type);
      • Containers will generally access controller object (View) if reference not set on container itself (next step)
        • ? What if subsequent containers have component reference directly?
          • Example: group container does not have reference, but view container does
          • Options
            1. Retrieve reference from container’s controller as fallback (current)
              • Only single container will be evaluated (since a valid reference will be returned from controller as fallback)
              • - Subsequent containers will not have a chance to retrieve reference
              • - Pointless to have multiple containers
            2. Do not use controller as fallback
              • Add additional parameter to get_component()to skip fallback
                var container = get_component('group', View.Group, false);
              • Return empty value if reference not found on component itself
              • + All containers will be evaluated
  4. Get reference to default component from controller
    • Controller (View) is set as parent of all components
    • Default component created if not previously created
    • Uses initialization options to build component instance with default properties
    • ? Do all components have a default?
      • Viewer: Yes
      • Theme: Yes
      • Group: No
        • ? Handling items without groups
          1. Ungrouped items are displayed singly (current)
            • No slideshow support for ungrouped items
            • + Clear/straightforward operation
            • + Server-side can add ungrouped items to group based on options (group by post, etc.)
          2. Display ungrouped items as group
            • Use a default group to group all items not explicitly placed in a group
            • Ungrouped items will be displayed as a slideshow
            • + Possible to easily cycle through ungrouped items
            • - Overrides admin options
            • - Items do not need to be grouped if they were not purposefully grouped
            • - Items that you want to display in isolation will need to have to be explicitly placed in their own group
      • Content Item: No
        • All content items are unique and should point to valid content
      • Content Type: No
        • All content types registered manually

Return value

  • Valid component type or NULL (e.g. if component reference not found)
  • Wrapper methods (get_group(), get_viewer(), etc.) can use return value to validate data and return appropriate value

Set component reference (process)

Arguments

  • Property name (string): Name of property to set (group, viewer, etc.)
  • Value (object|string): Component reference
    • string: ID of reference – stored in controller (View)
    • object: Component instance reference
  • Data type (Component Class [function]): Component type (View.Viewer, View.Group, etc.)
    • Required data type for component

Methodology

  1. Retrieve component instance from controller if ID supplied
    var component = this.get_parent().get_component(id, data_type);
    • ? What to do if component with matching ID does not exist in controller?
      • A: Options
        1. Return empty value (null)
          • Component reference not set on current object
          • Continue to next step (container iteration) if attempting to set invalid value in get_component() to find valid component reference
        2. Create new component
          • Use supplied ID to initialize new component instance
          • Use controller defaults/options to set new component’s properties
            • Controller options are parsed (if not already parsed) to provide access to component-specific options/properties
            • ? Use single method to initialize new components or use component-specific methods?
              • A: Options
                1. Single universal method
                  • Controller properties will need to parsed into groups so that new component will be passed appropriate values
                  • + Only one method to maintain when API changes, etc.
                  • + Components share same base definition (methods, properties, etc.)
                  • - Single method may become convoluted when components diverge a lot
                2. Component-specific methods
                  • Create specific method for initializing each component (View.add_group(), etc.)
                  • + These methods should exist anyway for adding components directly
                  • ? How to add components if component-specific method does not exist
                3. Component-specific + Universal method
                  • Use universal method (less specialized) if component-specific (more specialized) initialization method for component does not exist
                  • + Simple components may not need specialized methods
                  • + Allows more specialized creation of components as needed
          • + Object’s attributes say that component should exist
          • + Not overwriting anything – only creates new instance if ID does not exist
            • Can customize component instance properties later if necessary
          • New component instance saved to appropriate controller collection (Based on data type: View.groups, View.viewers, etc.)
  2. Save component reference to specified property type
    this.property = component;