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);