Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose an API for creating UI elements #188

Open
havok2063 opened this issue Aug 21, 2024 · 2 comments
Open

expose an API for creating UI elements #188

havok2063 opened this issue Aug 21, 2024 · 2 comments

Comments

@havok2063
Copy link

Is it possible to expose an API to create more complex custom UI elements? For example, I'd to create a button with a context menu, similar to the current Settings or Overlays button, with my own content. I'd also like to re-use some of your existing elements, like the color picker, or visibility, and remove buttons.

What is the best way to create more complex custom UI elements?

Or alternatively, is there an easy way to modify Aladin's existing elements? For example, adding a color picker option to a new Catalog layer, under the Overlays menu, to interactively change the source color?

@bmatthieu3
Copy link
Collaborator

It is not yet finished but here is a working example (with the latest) for setting a custom catalog setting ui to change its color:

<div id="aladin-lite-div" style="width: 1024px; height: 768px">
    <div class="box-content" style="width:200px">
        <div style="display:inline-flex">
            <label for="cat-color">Color</label>
            <input type="color" id="cat-color" value="#ff0000">
        </div>
       
    </div>
</div>

<script type="module">
    import A from '../src/js/A.js';
    let aladin;
    A.init.then(() => {
        var aladin = A.aladin(
            '#aladin-lite-div',
            {
                fov: 1.5, // initial field of view in degrees
                target: 'NGC 2175', // initial target
            }
        );

        // Add a catalog
        let cat = A.catalogFromSimbad('NGC 2175', 0.1, {onClick: 'showTable'});
        aladin.addCatalog(cat);

        // Logic for changing the color of catalog sources
        let colorPicker = document.querySelector('#cat-color');
        colorPicker.value = cat.color;
        colorPicker.addEventListener('input', function (e) {
            // Change the color of the catalog
            cat.updateShape({color: this.value});
        })

        // Define the box
        let catalogSettingsBox = A.box({
            header: {
                title: "Settings",
            },
            content: document.querySelectorAll('.box-content')[0],
        });
        catalogSettingsBox._hide();

        // Define the button that toggles the box
        let catalogSettingsBtn = A.button({
            content: 'Catalog',
            classList: ['catalogSettingsTogglerBtn'],
            action(o) {
                if (catalogSettingsBox.isHidden) {
                    catalogSettingsBox._show({
                        position: {
                            nextTo: catalogSettingsBtn,
                            direction: 'right',
                        }
                    })
                } else {
                    catalogSettingsBox._hide()
                }
            }
        });

        aladin.addUI(catalogSettingsBtn)
        aladin.addUI(catalogSettingsBox)
    });
</script>
<style>
    .catalogSettingsTogglerBtn {
        position: absolute;
        top: 200px;
        left: 0;
    }
</style>

I am not sure how to make the API better. I would tend to say user do not have to define the Box javascript object. Maybe, the user could add a specific class name (like aladin-box) to the div of a box which would be retrieved by aladin internally and Box objects could be created with the content. The user could then have all the boxes from the aladin object and could decide which he wants to show or hide (like a toggler button).

Would it be sufficient for your use case ?

@havok2063
Copy link
Author

havok2063 commented Sep 3, 2024

Thanks. I haven't been able to quite get this to work, but I haven't tested it against the latest main repo code. I tried adapting it in the live playground here, https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/marker-creation/, but the "Catalog" button does not open anything. But I'll try testing it again.

For expanding the API, I am imagining exposing all the current UI elements you use onto the A object, that lets the user combine different existing UI elements in new ways, e.g. A.colorBtn, or A.removeBtn. For example, to create a new button that when clicked, displays a stack of buttons with two rows: 1st row, a color picker button; 2nd row, a range slider button and a remove button.

        let myStack = A.stackBox({
           components: [A.colorBtn(), [A.sliderBtn(), A.removeBtn()] ] 
})

        let newBtn = A.button({
            content: 'Catalog',
            classList: ['newBtn'],
            id: 'newCatalogBtn',
            ctxMenu:  myStack,
        });
       aladin.addUI(newBtn)

Instantiating bare , e.g. A.colorBtn() would give you a default button, but it could also take options for adding event handlers or other config settings. I also think adding unique div ids to each element would be helpful for selection. To add a new color button to one specific Catalog Overlay layer, I might do something like

A.select('#catalog1Overlay').add(A.colorBtn, 0) 

which would add a new color picker button to the Catalog 1 Overlay before the Visibility button. This would also make it easier to assign existing elements to new button functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants