Browse Source

`output.scroll_to()` support `position` parameter

wangweimin 5 years ago
parent
commit
e28d14756d
2 changed files with 29 additions and 10 deletions
  1. 16 7
      pywebio/html/js/pywebio.js
  2. 13 3
      pywebio/output.py

+ 16 - 7
pywebio/html/js/pywebio.js

@@ -116,11 +116,13 @@
         else if (position === 'bottom')
         else if (position === 'bottom')
             scrollTopOffset = target[0].getBoundingClientRect().bottom - container[0].getBoundingClientRect().bottom;
             scrollTopOffset = target[0].getBoundingClientRect().bottom - container[0].getBoundingClientRect().bottom;
 
 
+        var speed = Math.min(Math.abs(scrollTopOffset), 500) + 100;
         if (scrollTopOffset !== null)
         if (scrollTopOffset !== null)
-            container.stop().animate({scrollTop: container.scrollTop() + scrollTopOffset}, Math.min(scrollTopOffset, 500) + 100, complete);
+            container.stop().animate({scrollTop: container.scrollTop() + scrollTopOffset}, speed, complete);
     }
     }
 
 
     var AutoScrollBottom = true;  // 是否有新内容时自动滚动到底部
     var AutoScrollBottom = true;  // 是否有新内容时自动滚动到底部
+    var OutputFixedHeight = false;  // 是否固定输出区域宽度
 
 
     OutputController.prototype.accept_command = ['output', 'output_ctl'];
     OutputController.prototype.accept_command = ['output', 'output_ctl'];
 
 
@@ -135,7 +137,8 @@
 
 
     OutputController.prototype.scroll_bottom = function () {
     OutputController.prototype.scroll_bottom = function () {
         // 固定高度窗口滚动
         // 固定高度窗口滚动
-        box_scroll_to(this.container_elem, this.container_parent, 'bottom');
+        if (OutputFixedHeight)
+            box_scroll_to(this.container_elem, this.container_parent, 'bottom');
         // 整个页面自动滚动
         // 整个页面自动滚动
         body_scroll_to(this.container_parent, 'bottom');
         body_scroll_to(this.container_parent, 'bottom');
     };
     };
@@ -212,11 +215,13 @@
             $('#title').text(msg.spec.title);  // 直接使用#title不规范 todo
             $('#title').text(msg.spec.title);  // 直接使用#title不规范 todo
             document.title = msg.spec.title;
             document.title = msg.spec.title;
         }
         }
-        if (msg.spec.output_fixed_height !== undefined)
+        if (msg.spec.output_fixed_height !== undefined) {
+            OutputFixedHeight = msg.spec.output_fixed_height;
             if (msg.spec.output_fixed_height)
             if (msg.spec.output_fixed_height)
                 $('.container').removeClass('no-fix-height');  // todo 不规范
                 $('.container').removeClass('no-fix-height');  // todo 不规范
             else
             else
                 $('.container').addClass('no-fix-height');  // todo 不规范
                 $('.container').addClass('no-fix-height');  // todo 不规范
+        }
         if (msg.spec.auto_scroll_bottom !== undefined)
         if (msg.spec.auto_scroll_bottom !== undefined)
             AutoScrollBottom = msg.spec.auto_scroll_bottom;
             AutoScrollBottom = msg.spec.auto_scroll_bottom;
         if (msg.spec.set_anchor !== undefined) {
         if (msg.spec.set_anchor !== undefined) {
@@ -227,10 +232,14 @@
             this.container_elem.find(`#${msg.spec.clear_before}`).prevAll().remove();
             this.container_elem.find(`#${msg.spec.clear_before}`).prevAll().remove();
         if (msg.spec.clear_after !== undefined)
         if (msg.spec.clear_after !== undefined)
             this.container_elem.find(`#${msg.spec.clear_after}~*`).remove();
             this.container_elem.find(`#${msg.spec.clear_after}~*`).remove();
-        if (msg.spec.scroll_to !== undefined)
-            $([document.documentElement, document.body]).animate({
-                scrollTop: $(`#${msg.spec.scroll_to}`).offset().top
-            }, 400);
+        if (msg.spec.scroll_to !== undefined) {
+            var target = $(`#${msg.spec.scroll_to}`);
+            if (OutputFixedHeight) {
+                box_scroll_to(target, this.container_parent, msg.spec.position);
+            } else {
+                body_scroll_to(target, msg.spec.position);
+            }
+        }
         if (msg.spec.clear_range !== undefined) {
         if (msg.spec.clear_range !== undefined) {
             if (this.container_elem.find(`#${msg.spec.clear_range[0]}`).length &&
             if (this.container_elem.find(`#${msg.spec.clear_range[0]}`).length &&
                 this.container_elem.find(`#${msg.spec.clear_range[1]}`).length) {
                 this.container_elem.find(`#${msg.spec.clear_range[1]}`).length) {

+ 13 - 3
pywebio/output.py

@@ -43,6 +43,9 @@ try:
 except ImportError:
 except ImportError:
     PILImage = type('MockPILImage', (), {})
     PILImage = type('MockPILImage', (), {})
 
 
+TOP = 'top'
+MIDDLE = 'middle'
+BOTTOM = 'bottom'
 
 
 def set_title(title):
 def set_title(title):
     r"""设置页面标题"""
     r"""设置页面标题"""
@@ -92,10 +95,17 @@ def clear_range(start_anchor, end_anchor):
     send_msg('output_ctl', dict(clear_range=[inner_start_anchor_name, inner_end_ancher_name]))
     send_msg('output_ctl', dict(clear_range=[inner_start_anchor_name, inner_end_ancher_name]))
 
 
 
 
-def scroll_to(anchor):
-    """将页面滚动到 ``anchor`` 锚点处"""
+def scroll_to(anchor, position=TOP):
+    """将页面滚动到 ``anchor`` 锚点处
+
+    :param str anchor: 锚点名
+    :param str position: 将锚点置于屏幕可视区域的位置。可用值:
+       * ``TOP`` : 滚动页面,让锚点位于屏幕可视区域顶部
+       * ``MIDDLE`` : 滚动页面,让锚点位于屏幕可视区域中间
+       * ``BOTTOM`` : 滚动页面,让锚点位于屏幕可视区域底部
+    """
     inner_ancher_name = 'pywebio-anchor-%s' % anchor
     inner_ancher_name = 'pywebio-anchor-%s' % anchor
-    send_msg('output_ctl', dict(scroll_to=inner_ancher_name))
+    send_msg('output_ctl', dict(scroll_to=inner_ancher_name, position=position))
 
 
 
 
 def _put_content(type, anchor=None, before=None, after=None, **other_spec):
 def _put_content(type, anchor=None, before=None, after=None, **other_spec):