From 787db85cd19867bf1daa7878d9bec2e9a9c8f431 Mon Sep 17 00:00:00 2001 From: Eli Mintz Date: Sun, 1 Mar 2020 21:56:16 -0500 Subject: [PATCH] 0.0.8 --- justpy/htmlcomponents.py | 26 +++++++++++++++++++++---- justpy/quasarcomponents.py | 6 ++++-- justpy/templates/js/html_component.js | 16 +++++++++++---- justpy/templates/js/quasar_component.js | 24 ++++++++++++++++++----- justpy/templates/main.html | 3 +++ 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/justpy/htmlcomponents.py b/justpy/htmlcomponents.py index 0a559689..e2b2c93d 100644 --- a/justpy/htmlcomponents.py +++ b/justpy/htmlcomponents.py @@ -124,6 +124,16 @@ def get_components(self): def last(self): return self.components[-1] + async def run_javascript(self, javascript_string): + try: + websocket_dict = WebPage.sockets[self.page_id] + except: + return self + dict_to_send = {'type': 'run_javascript', 'data': javascript_string} + await asyncio.gather(*[websocket.send_json(dict_to_send) for websocket in list(websocket_dict.values())], + return_exceptions=True) + return self + async def update_old(self, *, built_list=None): try: websocket_dict = WebPage.sockets[self.page_id] @@ -311,7 +321,7 @@ class HTMLBaseComponent(JustpyBaseComponent): html_global_attributes = ['accesskey', 'class', 'contenteditable', 'dir', 'draggable', 'dropzone', 'hidden', 'id', 'lang', 'spellcheck', 'style', 'tabindex', 'title'] - attribute_list = ['id', 'vue_type', 'show', 'events', 'classes', 'style', 'focus', + attribute_list = ['id', 'vue_type', 'show', 'events', 'classes', 'style', 'set_focus', 'html_tag', 'class_name', 'event_propagation', 'inner_html', 'animation', 'debug'] # not_used_global_attributes = ['dropzone', 'translate', 'autocapitalize', @@ -340,7 +350,7 @@ def __init__(self, **kwargs): self.animation = False self.pages = {} # Dictionary of pages the component is on. Not managed by framework. self.show = True - self.focus = False + self.set_focus = False self.classes = '' self.slot = None self.scoped_slots = {} # For Quasar and other Vue.js based components @@ -410,6 +420,14 @@ def add_allowed_event(self, event_type): def add_scoped_slot(self, slot, c): self.scoped_slots[slot] = c + def remove_class(self, tw_class): + class_list = self.classes.split() + try: + class_list.remove(tw_class) + except: + pass + self.classes = ' '.join(class_list) + def to_html(self, indent=0, indent_step=0, format=True): block_indent = ' ' * indent if format: @@ -757,7 +775,7 @@ def convert_object_to_dict(self): return d -class TextArea(Input): +class Textarea(Input): html_tag = 'textarea' attributes = ['autofocus', 'cols', 'dirname', 'disabled', 'form', 'maxlength', 'name', @@ -839,7 +857,7 @@ def convert_object_to_dict(self): return d -class EditorMD(TextArea): +class EditorMD(Textarea): # https://www.cssportal.com/style-input-range/ style an input range # Set the page's tailwind attribute to False for preview to work def __init__(self, **kwargs): diff --git a/justpy/quasarcomponents.py b/justpy/quasarcomponents.py index 087c13c4..1e5e0916 100644 --- a/justpy/quasarcomponents.py +++ b/justpy/quasarcomponents.py @@ -48,6 +48,7 @@ def __setattr__(self, key, value): class _QInputBase(Input): slots = [] + evaluate_prop = [] def __init__(self, **kwargs): super().__init__(**kwargs) @@ -88,7 +89,7 @@ def convert_object_to_dict(self): d = super().convert_object_to_dict() if self.disable_events: d['events'] = [] - + d['evaluate_prop'] = self.evaluate_prop return d @@ -109,6 +110,7 @@ def __init__(self, **kwargs): 'placeholder'] self.allowed_events = ['keypress', 'input', 'focusin', 'focusout'] # Not different from focus and blur in documentation + self.evaluate_prop = ['rules'] @parse_dict @@ -808,7 +810,7 @@ def __init__(self, **kwargs): self.type = 'boolean' self.value = bool(self.value) self.prop_list = ['transition-show', 'transition-hide', 'target', 'delay', 'max-height', 'max-width', 'value', - 'anchor', 'self', 'offset', 'content-class', 'content-style'] + 'anchor', 'self', 'offset', 'content-class', 'content-style', 'hide-delay'] self.allowed_events = ['input', 'show', 'before_show', 'hide', 'before_hide'] diff --git a/justpy/templates/js/html_component.js b/justpy/templates/js/html_component.js index 2069227b..7598401b 100644 --- a/justpy/templates/js/html_component.js +++ b/justpy/templates/js/html_component.js @@ -145,9 +145,17 @@ Vue.component('html_component', { var animation = this.$props.jp_props.animation; var element = this.$el; element.classList.add('animated', animation); - element.addEventListener('animationend', function () { + element.classList.remove('hidden'); + var event_func = function() { element.classList.remove('animated', animation); - }); + if (animation.includes('Out')) { + element.classList.add('hidden'); + } else { + element.classList.remove('hidden'); + } + element.removeEventListener('animationend', event_func); + }; + element.addEventListener('animationend', event_func); }) }, @@ -159,7 +167,7 @@ Vue.component('html_component', { this.$refs['r' + this.$props.jp_props.id].value = this.$props.jp_props.value; } - if (this.$props.jp_props.focus) { + if (this.$props.jp_props.set_focus) { this.$nextTick(() => this.$refs['r' + this.$props.jp_props.id].focus()) } @@ -187,7 +195,7 @@ Vue.component('html_component', { } } - if (this.$props.jp_props.focus) { + if (this.$props.jp_props.set_focus) { this.$nextTick(() => this.$refs['r' + this.$props.jp_props.id].focus()) } diff --git a/justpy/templates/js/quasar_component.js b/justpy/templates/js/quasar_component.js index c52ec4cd..e3a42483 100644 --- a/justpy/templates/js/quasar_component.js +++ b/justpy/templates/js/quasar_component.js @@ -1,16 +1,16 @@ // {% raw %} var storage_dict = {}; -// var comp_dict = {}; // moved to main.html Vue.component('quasar_component', { render: function (h) { + if (this.jp_props.hasOwnProperty('text')) { var comps = [this.jp_props.text]; } else comps = []; for (var i = 0; i < this.jp_props.object_props.length; i++) { - if (this.jp_props.object_props[i].show) { // (this.jp_props.show) + if (this.jp_props.object_props[i].show) { comps.push(h(this.jp_props.object_props[i].vue_type, { props: { jp_props: this.jp_props.object_props[i] @@ -19,6 +19,20 @@ Vue.component('quasar_component', { } } + if (this.jp_props.evaluate_prop && (this.jp_props.evaluate_prop.length > 0)) { + for (i = 0; i < this.jp_props.evaluate_prop.length; i++) { + const evaluated_prop = this.jp_props.evaluate_prop[i]; + if (this.jp_props.attrs[evaluated_prop]) { + if (typeof this.jp_props.attrs[evaluated_prop] == 'string') { + this.jp_props.attrs[evaluated_prop] = eval(this.jp_props.attrs[evaluated_prop]) + } else { + for (let j = 0; i < this.jp_props.attrs[evaluated_prop].length; i++) { + this.jp_props.attrs[evaluated_prop][j] = eval(this.jp_props.attrs[evaluated_prop][j]); + } + } + } + } + } description_object = { style: this.jp_props.style, @@ -74,7 +88,7 @@ Vue.component('quasar_component', { case 'load': fn = this.loadEvent; break; - // For Qtable + // For QTable case 'update:pagination': fn = this.tablePaginationEvent; break; @@ -319,7 +333,7 @@ Vue.component('quasar_component', { this.$refs['r' + this.$props.jp_props.id].value = this.$props.jp_props.value; } - if (this.$props.jp_props.focus) { + if (this.$props.jp_props.set_focus) { this.$nextTick(() => this.$refs['r' + this.$props.jp_props.id].focus()) } }, @@ -375,7 +389,7 @@ Vue.component('quasar_component', { } } - if (this.$props.jp_props.focus) { + if (this.$props.jp_props.set_focus) { this.$nextTick(() => this.$refs['r' + this.$props.jp_props.id].focus()) } }, diff --git a/justpy/templates/main.html b/justpy/templates/main.html index cca2b4ad..180603d2 100644 --- a/justpy/templates/main.html +++ b/justpy/templates/main.html @@ -86,6 +86,9 @@ // update just specific component on the page comp_replace(msg.data, app1.justpyComponents); break; + case 'run_javascript': + eval(msg.data); + break; case 'run_method': // await websocket.send_json({'type': 'run_method', 'data': command, 'id': self.id}) eval('comp_dict[' + msg.id+ '].' + msg.data);