# # UI Fragments

Fragments are a set of UI snippets, which can be used to insert,delete, or modify the components in UI template. It is suitable to facilitate a small amount of UI customization based on built-in templates.

If you need a lot of custom layout and device adaptation, please refer to the methods described in Appearance and layout template.

## # simple example

The following code will use fragments configuration to remove the `comment-tab` component from the mobile and desktop/tablet layouts. Click `run` to run the example, and you can use the device mode of Chrome DevTool to simulate the running effect of mobile/tablet.

    <script>
        var CustomAppearance= UIExtension.appearances.AdaptiveAppearance.extend({
            getDefaultFragments: function() {
                var isMobile = PDFViewCtrl.DeviceInfo.isMobile;
                if(isMobile) {
                    // Fragment configuration for mobile devices.
                    return [{
                        target: 'comment-tab',
                        action: 'remove'
                    },{
                        target: 'comment-tab-li',
                        action: 'remove'
                    }, {
                        target: 'comment-tab-body',
                        action: 'remove'
                    }];
                } else {
                    // Fragment configuration for desktop/tablet devices.
                    return [{
                        target: 'comment-tab',
                        action: 'remove'
                    }, {
                        target: 'fv--comment-tab-paddle',
                        action: 'remove'
                    }, {
                        target: 'hand-tool',
                        config: {
                            callback: {
                                around: function(callback, args) {
                                    try{
                                        console.info('before callback');
                                        var ret;
                                        if(callback instanceof UIExtension.Controller) {
                                            ret = callback.handle(...args);
                                        } else {
                                            ret = callback.apply(this, args);
                                        }
                                        console.info('after callback');
                                        return ret;
                                    }catch(e) {
                                        console.error(e, 'an error occurred');
                                    } finally {
                                        console.info('');
                                    }
                                }
                            }
                        },
                    }];
                }
            }
        });
        var libPath = window.top.location.origin + '/lib';

        var pdfui = new UIExtension.PDFUI({
                viewerOptions: {
                    libPath: libPath,
                    jr: {
                        licenseSN: licenseSN,
                        licenseKey: licenseKey
                    }
                },
                renderTo: document.body,
                // Different appearances are available depending on the device type.
                appearance: CustomAppearance,
                addons: []
        });
    </script>

    {
        "iframeOptions": {
            "style": "height: 500px",
            "injectCss": [
                "/lib/UIExtension.vw.css"
            ]
        }
    }

## # The description of the Fragment configuration parameters

- `target`: The name of the control, and each name is unique.
- `action`: Indicates the action mode of the fragment snippets. The default action mode is `UIExtension.UIConsts.FRAGMENT_ACTION.EXT`. The specifics are as follows:
  - `UIExtension.UIConsts.FRAGMENT_ACTION.EXT`: Extend the target control.
  - `UIExtension.UIConsts.FRAGMENT_ACTION.BEFORE`: Insert a new control before the target control.
  - `UIExtension.UIConsts.FRAGMENT_ACTION.AFTER`: Insert a new control after the target control.
  - `UIExtension.UIConsts.FRAGMENT_ACTION.APPEND`: Insert a new control into the target control (the target control must be a container).
  - `UIExtension.UIConsts.FRAGMENT_ACTION.FILL`: Empty the child space of the target control and fill with a new control. Make sure that the target control must be a container.
  - `UIExtension.UIConsts.FRAGMENT_ACTION.REPLACE`: Replace the target control with a new control.
  - `UIExtension.UIConsts.FRAGMENT_ACTION.REMOVE`: Delete the target control.
- `template`: The template of the control. The content is in XML format and action is BEFORE/AFTER/APPEND/FILL/REPLACE.
- `config`: Control configuration object. It is invalid when action is REMOVE.

  - `config.target`: The name of the control in the above template. It is only required when action is BEFORE/AFTER/APPEND/FILL/REPLACE.

  - `config.attrs`: Set the html property of the control.

  - `config.callback`: The business logic implementation of the control. There are three ways to implement it:

    - function: The events of control will call this function, and override the built-in callbacks. The basic components that support function are (xbutton, dropdown-button, context-menu-item). If you want to add functionalities based on the built-in callbacks, you can use the second method.

    - controller class: Controller class can listen for components lifecycle and handle more component events:

          {
              target: 'hand-tool',
              config: {
                  callback: class extends UIExtension.Controller {
                      mounted() {
                          super.mounted();
                          this.component.element.addEventListener('hover', e => {
                              console.info('mouse over', this.component)
                          })
                      }
                      handle() {
                          console.info('hand-tool clicked')
                      }
                  }
              }
          }

    - decorator object: it contains a series of function hooks for blocking the execution of the controller handle method, including before, after, thrown, and around.

          {
              target: 'hand-tool',
              config: {
                  callback: {
                      before: function() {
                          // The function executed before calling the handle method of controller. It can receive all parameters of the handle method.
                      },
                      after: function(returnValue) {
                         // The function executed after calling the handle method of controller. It can receive the return value and parameters of the handle function.
                      },
                      thrown: function(error) {
                          // The function executed when the handle method of controller throws an exception. It can receive the exception object and parameters.
                      },
                      around: function(callback, args) {
                          // It can receive the references and parameters of controller's handle method. Inside the around callback, you can execute code before/after running the handle function, or in the catch exception block. It also can decide whether to execute the handle method.

                          try{
                              console.info('before callback');
                              var ret;
                              if(callback instanceof UIExtension.Controller) {
                                  ret = callback.handle(...args);
                              } else {
                                  ret = callback.apply(this, args);
                              }
                              console.info('after callback');
                              return ret;
                          }catch(e) {
                              console.error(e, 'an error occurred');
                          } finally {
                              console.info('');
                          }
                      }
                  }
              }
          }

## # Note

> It is recommended that only use fragment for UI fine-tuning. If you want to substantially modify the built-in layout, please refer to the methods described in Appearance and layout template.