maxence-charriere / go-app

A package to build progressive web apps with Go programming language and WebAssembly.
https://go-app.dev
MIT License
7.9k stars 362 forks source link

Prevent opening image in new tab #772

Closed zeljkosh closed 4 months ago

zeljkosh commented 2 years ago

Hello, i have a following code

app.A().Class("d-block mb-4 h-100 rounded").Body(
                    app.Img().Class("rounded img-fluid").Src("https://lipsum.app/id/61/400x300").Alt(""),
                ).DataSet("fancybox", "gallery").Href("https://lipsum.app/id/61/1600x1200"),
            ),

normally this just zooms in the image, but in goApp it also opens the image in new tab, i tried intercepting the on click event, but then instead of blocking the opening image in new tab, it blocks the zoom from happening, but image get still open in new tab.

I am not sure why this happens, if i for example put the static image, then it opens nicely, but when i close i get 404 error since now the url is not / but /web/nameofmyimage.png

oderwat commented 2 years ago

At first sight, I think there may be just a .Href("#'"). missing. If not, the element may not be bound to a handler. So updating that after rendering your component would be the solution.

zeljkosh commented 2 years ago

What do you mean ? the href is there, after DataSet(). Second part i dont understand, which element is not bound to handler ? the img element ? And how would i achieve something like that ? I just dont want that clicking on img == new route, but i am unable to intercept that element and prevent it from redirecting

oderwat commented 2 years ago

I thought you had some code that opens the image inline and zooms it by replacing that code with its magic. If you just want to open this image (with an external URL) you need to tell Go-App that you do not want it in another tab. Take a look at app.Handler:

    // The URLs that are launched in the app tab or window.
    //
    // By default, URLs with a different domain are launched in another tab.
    // Specifying internal URLs is to override that behavior. A good use case
    // would be the URL for an OAuth authentication.
    InternalURLs []string
zeljkosh commented 2 years ago

I can do that, (for the external URLS) how ever , issue is that for internal data, it adds path to URL, so what happens at the moment is https://localhost:8000/ i click on an image https://localhost:8000/web/img/mycoolimg.jpg#galery1 Now 2 important things, on normal html code, i just get 8000/#galery1 with goApp i get path to the resource, basicly this works now, it opens image galery and i can scroll through it, but it points to non existing link so i also get error 404.

maybe if i could redirect all /web/img/* paths to /, but i did not find something like that at routing part of documentation.

As you can see in screeshots, first time clicking the image in this case "heart.jpg", enters also path to my url, after that only last number of galery changed, but i dont want to append the /web/img/heart.jpg to my path at all. This is my issue.

Thanks!

Screenshot from 2022-09-05 20-44-14 Screenshot from 2022-09-05 20-44-27

oderwat commented 2 years ago

I do not understand why you want to replace the website with the jpg image URL in the first place. Something is going on that I do not grasp for sure. If you want to route something to the root of the application path, you can use another config parameter.

    // The static resources that are accessible from custom paths. Files that
    // are proxied by default are /robots.txt, /sitemap.xml and /ads.txt.
    ProxyResources []ProxyResource

But that is not flexible. Adding a route with a fileserver in the backend (aka server) would be better.

Still, all of this sounds odd to me. "on normal html code, i just get 8000/#galery1" sounds like exactly what I assumed before is going on. There is something that creates an "inline" gallery. This would most likely work quite differently in the context of the Go-App. I fear I can't understand what is happening without looking at the code itself.

zeljkosh commented 2 years ago

Hey, thanks for trying to help ,

so this is html (svelte code) https://pastebin.com/QKzaYEvM

The only thing needed is to add the js and css for fancy box and it will work.

<script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0dist/fancybox.css"/>

I assume that issue here is that the js library "catches" click on image in normal html and does not send user to /web/ static folder, which in go does not happen. I did not manage to find workaround for the time being.

oderwat commented 2 years ago

I think it is just what I wrote in my first comment: "the element may not be bound to an (event) handler".

You can't use those javascript scripts with Go-App and just expect them to work in the same way. Besides that, you should avoid loading something from a CDN because Go-App is meant to run as PWA, and this means even without an internet connection (that is the reason it caches everything and used the web-worker fetch interface)

Basically, it is similar to what I described in #770. Fancybox seems even more complicated, as it is a jQuery() based extension. To use it you need to call the jQuery functions after creating your page (OnRender) in the front end. So you would render, and then in OnMount, you need to call something like $(".selector").fancybox(); from Go-App to add the FancyBox code to all the new elements. I think putting this inside a function that gets loaded through as <script>function updateFancyBox {$(".fbox").fancybox();}</script> through the RawHeaders could work. Add that FancyBox script to app.Handler.Scripts (I would load it from the CDN and put it into /web/). Then after your "OnRender" was called and "OnMount" is running, you can call app.Window().Call("updateFanyBox") through ctx.Defer() to apply the handlers to the code (which uses the class "fbox" in addition to the others on the related tags).

I think "you people" do not realize that Go-App lets you write your own composable "FancyBox" component in pure Go and just use that instead of importing all those java-scripts which were meant to be used in something like Svelte/VueJS/React/Angular or maybe just jQuery. I try not to touch any javascript with all my Go-Apps, but if, one really needs to know how Go-App works, and what the lifetimes of the components are. When stuff gets rendered and updated and so on.

Edit: `app.Window().Call("$",".fbox").Call("fancybox()") probably works too, instead of the stub. I am just not sure :)

zeljkosh commented 2 years ago

Thanks a lot, i will try to see what can i do. I was using this mostly as playground to see what it can be done, i also do not want to have any bootstrap libraries or jquery in goApp later.

Now to the second part, i think that there is very few examples how to achieve these things in goApp, there is no example on how to create simple navbar, that colapses when size is reduced. Should we use media query for the size settings or do it somehow through go ? I tryed to use the demo application from go-app-demo repo, and its not working, its outdated and it uses componenets that have been deprecated.

So i really would like to do things, go way, but there simple are not enough comperhensive resources.

Thank you one more time for your help, i will try to get this to work just to see what would happen, then later i might try to do something like this in pure go

oderwat commented 2 years ago

My left-side collapsing nav bar component uses TailwindCSS breakpoints for the actual collapsing and always renders the collapsed and the full version when the navigation changes (like logging in and out). Then it uses some internal state (stored as part of the sitemap) that is then used by "OnRender" to change what gets shown. This state is to remember what the user opened and is changed through eventHandlers (OnClick) on the elements that open/close sections. It also hooks into "OnNav" to follow the selected URL (route) and is also used by OnRender to create the HTML that indicates where in the navigation we are. Finally, I use a complex sitemap to know what pages exist and what the navigation contains (filtered by roles).

Sadly, we are so deep in developing a pretty big and highly opinionated framework that is proprietary to our company that much of the code is interwoven with all the other components. I can't show examples of that. We are working on some more accessible examples, though, and will publish some of them to help the community besides doing what we do right now with sponsoring & contributing to Go-App.