Page Resize Events

I often want to show completely different forms if the user’s screen is below a certain size (eg mobile), as I am completely unable to create multi-device forms that resize well and look good.

I’ve only tried this in a SPA (ie the main form remains open throughout) using the Material design. Hope it’s useful to someone.

Please correct or better the code if you can/want to. I am even less of a JS expert than I am Python …

In your standard-page.html which is provided when you choose “Standard Page” as your form, put the following at the end :

<!-- unique ID required for anvil call backs form JS -->
<div id="main-page-id"></div>
  
<script>
  // Required to send you an initial page size.
  $( document ).ready(function() {
    resizedw();
  });
  
  function calculatePageWidth() {
    var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    return(w);
  }

  // This resizing pseudo-throttling routine was got from here :
  //	https://stackoverflow.com/questions/5489946/jquery-how-to-wait-for-the-end-of-resize-event-and-only-then-perform-an-ac
  // It's the answer under the accepted one.

  function resizedw(){
    anvil.call($('#main-page-id'), "page_resize_event", calculatePageWidth());
  }

  var doit;
  window.onresize = function(){
    clearTimeout(doit);
    doit = setTimeout(resizedw, 100);
  };  
  
</script>

Then create this method in your form :

  def page_resize_event(self,page_size_px):
    print("Page Resize Event - new size : "+str(page_size_px)+" px")

In that method you can choose what to do with that resize event. I set a form property that allows me to determine which child form to load.

6 Likes

Make it reusable :

  1. Create a new project (custom HTML) and create a Custom HTML form. I’ve named my project “ClientTools” and my form “PageResizeDetector”

  2. Edit the Custom HTML in the IDE for this form, replacing what’s there with the HTML/JSS above.

  3. Make the form a component, and add an event called page_resize_event :

  1. In the form code, add this function which is called from the javascript and in turn raises the event for your main project :
  def page_resize_event(self,page_size_px):
    self.raise_event("page_resize_event",page_size=page_size_px)
  1. Create a new project (Material Design), and add the ClientTools project as a dependency. When you do so, the PageResizeDetector form should appear as a custom component in the IDE.

  2. Drag a column panel onto the left hand menu column (where you would also add links for your menus), and drag your custom component form here too.

  3. Add this code to your main form :

  def __init__(self, **properties):
    ...    
    self.page_size = 0
    self.page_resize_detector_1.set_event_handler("page_resize_event",self.resize_event)
        
  def resize_event(self,**kwargs):
    self.page_size = kwargs['page_size']
    print("New Window Size : ", self.page_size)

If anyone knows a better way, please share :slight_smile:

2 Likes

Thanks for this example.

I feel like I’m missing something obvious here, could you show an example in of it being used?

Edit: Ignore above, figured it out.

This is amazing! Thanks so much David. I dread to think how many hours I would have spent on this in the alternate reality where you hadn’t posted this!

2 Likes

Here is an alternative way. Can be done on a per form basis directly from python through import anvil.js module.

Add this to init:

anvil.js.window.addEventListener("resize", self.resize_event)

add this to the class:

def resize_event(self, event):
  print(anvil.js.window.innerWidth, 
        anvil.js.window.document.documentElement.clientWidth,
        anvil.js.window.document.body.clientWidth)
1 Like