浏览代码

evaluate examples lazily

Falko Schindler 2 年之前
父节点
当前提交
2d1c00b92b
共有 5 个文件被更改,包括 52 次插入3 次删除
  1. 1 0
      main.py
  2. 12 2
      website/example.py
  3. 16 0
      website/intersection_observer.js
  4. 22 0
      website/intersection_observer.py
  5. 1 1
      website/reference.py

+ 1 - 0
main.py

@@ -229,6 +229,7 @@ ui.run()
 def reference_page():
 def reference_page():
     add_head_html()
     add_head_html()
     add_header()
     add_header()
+    ui.add_head_html('<style>html {scroll-behavior: auto;}</style>')
     with ui.column().classes('w-full p-8 lg:p-16 max-w-[1600px] mx-auto'):
     with ui.column().classes('w-full p-8 lg:p-16 max-w-[1600px] mx-auto'):
         section_heading('Documentation and Examples', '*API* Reference')
         section_heading('Documentation and Examples', '*API* Reference')
         reference.create_full()
         reference.create_full()

+ 12 - 2
website/example.py

@@ -7,6 +7,8 @@ import docutils.core
 from nicegui import ui
 from nicegui import ui
 from nicegui.elements.markdown import apply_tailwind
 from nicegui.elements.markdown import apply_tailwind
 
 
+from .intersection_observer import IntersectionObserver as intersection_observer
+
 REGEX_H4 = re.compile(r'<h4.*?>(.*?)</h4>')
 REGEX_H4 = re.compile(r'<h4.*?>(.*?)</h4>')
 SPECIAL_CHARACTERS = re.compile('[^(a-z)(A-Z)(0-9)-]')
 SPECIAL_CHARACTERS = re.compile('[^(a-z)(A-Z)(0-9)-]')
 PYTHON_BGCOLOR = '#e3e9f2'
 PYTHON_BGCOLOR = '#e3e9f2'
@@ -19,9 +21,13 @@ BROWSER_COLOR = '#ffffff'
 
 
 class example:
 class example:
 
 
-    def __init__(self, content: Union[Callable, type, str], browser_title: Optional[str] = None) -> None:
+    def __init__(self,
+                 content: Union[Callable, type, str],
+                 browser_title: Optional[str] = None,
+                 immediate: bool = False) -> None:
         self.content = content
         self.content = content
         self.browser_title = browser_title
         self.browser_title = browser_title
+        self.immediate = immediate
 
 
     def __call__(self, f: Callable) -> Callable:
     def __call__(self, f: Callable) -> Callable:
         with ui.column().classes('w-full mb-8'):
         with ui.column().classes('w-full mb-8'):
@@ -59,7 +65,11 @@ class example:
                 with python_window(classes='w-full max-w-[48rem]'):
                 with python_window(classes='w-full max-w-[48rem]'):
                     ui.markdown(code)
                     ui.markdown(code)
                 with browser_window(self.browser_title, classes='w-full max-w-[48rem] xl:max-w-[20rem] min-h-[10rem] browser-window'):
                 with browser_window(self.browser_title, classes='w-full max-w-[48rem] xl:max-w-[20rem] min-h-[10rem] browser-window'):
-                    f()
+                    if self.immediate:
+                        f()
+                    else:
+                        intersection_observer(on_intersection=f)
+
         return f
         return f
 
 
 
 

+ 16 - 0
website/intersection_observer.js

@@ -0,0 +1,16 @@
+export default {
+  template: '<div style="position: absolute"></div>',
+  mounted() {
+    this.interval = setInterval(() => {
+      const rect = this.$el.getBoundingClientRect();
+      if (rect.bottom > -window.innerHeight && rect.top < 2 * window.innerHeight) {
+        this.$emit("intersection");
+      }
+    }, 100);
+  },
+  methods: {
+    stop() {
+      clearInterval(this.interval);
+    },
+  },
+};

+ 22 - 0
website/intersection_observer.py

@@ -0,0 +1,22 @@
+from typing import Callable
+
+from nicegui.element import Element
+from nicegui.events import EventArguments, handle_event
+from nicegui.vue import register_component
+
+register_component('intersection_observer', __file__, 'intersection_observer.js')
+
+
+class IntersectionObserver(Element):
+
+    def __init__(self, *, on_intersection: Callable) -> None:
+        super().__init__('intersection_observer')
+        self.on_intersection = on_intersection
+        self.active = True
+        self.on('intersection', self.handle_intersection)
+
+    def handle_intersection(self, _) -> None:
+        self.run_method('stop')
+        if self.active:
+            handle_event(self.on_intersection, EventArguments(sender=self, client=self.client))
+            self.active = False

+ 1 - 1
website/reference.py

@@ -474,7 +474,7 @@ You can run a function or coroutine as a parallel task by passing it to one of t
 - `ui.on_disconnect`: Called when a client disconnects from NiceGUI. (Optional argument: socket)
 - `ui.on_disconnect`: Called when a client disconnects from NiceGUI. (Optional argument: socket)
 
 
 When NiceGUI is shut down or restarted, the startup tasks will be automatically canceled.
 When NiceGUI is shut down or restarted, the startup tasks will be automatically canceled.
-''')
+''', immediate=True)
     def lifecycle_example():
     def lifecycle_example():
         import asyncio
         import asyncio