Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions examples/jqueryselect2/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
== Description ==

This is an example of how to integrate a complex jQuery component with pyjs.

Here we integrate Select2 to implement a tagging component.
Not all functionality of Select2 is implemented. Only:

- set / get values
- receive change notifications

== Issues ==

pyjd is not supported (doesn't do javascript)

The CSS is not right
75 changes: 75 additions & 0 deletions examples/jqueryselect2/Select2TaggingComponent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from pyjamas.ui.HTML import HTML
from pyjamas import logging
from __pyjamas__ import JS
from __pyjamas__ import wnd

log = logging.getConsoleLogger()

class Select2TaggingComponent(HTML):

def __init__(self, tags = None, width = 300, selected = None, myid = 'select2example'):
#log.info("tags='%s' width='%s' selected='%s'", tags, width, selected)
self.myid = myid
self.tags = tags
# This markup is used by select2 to configure the component
html = '<p><input type="hidden" id="%s" style="width:%dpx"/></p>' % (myid, width)
html += '<div id="%s-show"></div>' % (myid)
self.selected = selected
log.info("html = '%s'", html)
HTML.__init__(self, html)

def get_val(self):
# This uses select2 to get the value of the element
myjs = 'parent.jQuery("#%s").select2("val");' % (self.myid)
return JS(""" eval(@{{myjs}}) """)

def change(self):
# This will be fired whenever the select2 component changes
pass

def update(self, values):
values_js = []
for value in values:
values_js.append('{id:"%s", text:"%s"}' % (value['id'], value['text']))
values_js = ','.join(values_js)
myjs = 'parent.jQuery("#%s").select2("val", [%s]);' % (self.myid, values_js)
log.info("Now calling JS: %s", myjs)
JS(""" eval(@{{myjs}}) """)

def bind_js_show(self):
# This is a pure javascript function, which can be triggered by binding with jQuery
# the "change" event to it
show = '''
function show() {
var e=parent.jQuery("<div style='background-color:yellow;'>change fired</div>");
parent.jQuery("#%s-show").append(e);
e.animate({opacity:0}, 1000, 'linear', function() { e.remove(); });
};''' % (self.myid)
myjs = '%s parent.jQuery("#%s").bind("change", show);' % (show, self.myid)
log.info("Now calling JS: %s", myjs)
JS(""" eval(@{{myjs}}) """)

def bind_pyjs_change(self):
# Here we bind the change event to the self.change pyjs method
# Since we are binding a global function to the self.change method, we want
# that global function to be unique (or at least to have the myid suffix)
global_unique_change = "change_%s" % (self.myid)
setattr(wnd(),global_unique_change,self.change)
# Now bind the change event to the wnd().global_unique_change function, which is actually self.change
myjs = 'parent.jQuery("#%s").bind("change", function() { parent.%s() });' % (self.myid, global_unique_change)
log.info("Now calling JS: %s", myjs)
JS(""" eval(@{{myjs}}) """)

def final_setup(self):
# Since select2 acts on the DOM, this can only be called once the component has been added to the DOM.
if self.tags:
tags = ','.join(['"%s"' % (tag) for tag in self.tags])
else:
tags = ''
myjs = 'parent.jQuery("#%s").select2({tags:[%s]});' % (self.myid, tags)
# TODO: what about self.selected?
log.info("Now calling JS: %s", myjs)
JS(""" eval(@{{myjs}}) """)
self.bind_js_show() # Bind a jQuery function
self.bind_pyjs_change() # Bind a pyjs method

73 changes: 73 additions & 0 deletions examples/jqueryselect2/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os

head = os.path.dirname(__file__)

TARGETS = {
'jQuerySelect2.py': dict(
downloads=[
dict(
url=
"http://code.jquery.com/"+\
"jquery-1.7.2.min.js",
dst=os.path.join(head, 'public', 'jquery.min.js'),
unzip=False,
),
dict(
url=
"https://github.com/downloads/ivaynberg/"+\
"select2/select2-2.1.zip",
dst=os.path.join(head, 'public', 'select2'),
unzip=True,
),
],
)
}


PACKAGE = {
'title': 'jQuery and Select2',
'desc': 'Integration of jQuery, Select2 and Pyjs Example',
}


def setup(targets):
'''Setup example for translation, MUST call util.setup(targets).'''
util.setup(targets)


def translate():
'''Translate example, MUST call util.translate().'''
util.translate()


def install(package):
'''Install and cleanup example module. MUST call util.install(package)'''
util.install(package)


##---------------------------------------##
# --------- (-: DO NOT EDIT :-) --------- #
##---------------------------------------##


import sys
import os


examples = head = os.path.abspath(os.path.dirname(__file__))
while os.path.split(examples)[1].lower() != 'examples':
examples = os.path.split(examples)[0]
if not examples:
raise ValueError("Cannot determine examples directory")
sys.path.insert(0, os.path.join(examples))
from _examples import util
sys.path.pop(0)

util.init(head)

setup(TARGETS)
translate()
install(PACKAGE)
75 changes: 75 additions & 0 deletions examples/jqueryselect2/jQuerySelect2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import pyjd # this is dummy in pyjs

from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.Button import Button
from pyjamas.ui.DialogBox import DialogBox
from pyjamas import logging
from pyjamas import Window

from Select2TaggingComponent import Select2TaggingComponent

log = logging.getConsoleLogger()

class MyTagger(VerticalPanel):

def __init__ (self, tags = None, width = 300, selected = None, myid = None):
VerticalPanel.__init__(self)
self.s2 = Select2TaggingComponent(tags, width, selected, myid)
self.reset_button = Button("Reset", self)
self.show_values_button = Button("Show", self)
self.add(self.s2)
self.add(self.reset_button)
self.add(self.show_values_button)
self.s2.change = self.change

def change(self):
txt = "Object with id=%s has value '%s'" % (self.s2.myid, self.s2.get_val())
log.info(txt)
self.create_popup(txt)

def create_popup(self, txt):
popup = DialogBox(False, False)
popup.onClick = lambda w: popup.hide()
popup.setHTML('<b>%s</b>' % (txt))
popup.setWidget(Button('Close', popup))
popup.show()

def onClick(self, sender):
if sender == self.reset_button:
log.info('Updating')
values = [ { 'id' : 'id1', 'text': 'text1'}, { 'id' : 'id2', 'text': 'text2'}]
self.s2.update(values)
elif sender == self.show_values_button:
txt = "Object with id=%s has value '%s'" % (self.s2.myid, self.s2.get_val())
log.info(txt)
self.create_popup(txt)

class MainWindow:

def onModuleLoad(self):

# TODO: the change event does not work properly when there are
# several Select2TaggingComponent.
tagger1 = MyTagger(myid = 'example1')
tagger2 = MyTagger(myid = 'example2')

# Get rid of scrollbars, and clear out the window's built-in margin,
# because we want to take advantage of the entire client area.
Window.enableScrolling(False)
Window.setMargin("0px")

# Add the component to the DOM
RootPanel().add(tagger1)
RootPanel().add(tagger2)

# Now that it is in the DOM, select2 can perform the final setup
# TODO: is it possible that the component automatically detects this?
tagger1.s2.final_setup()
tagger2.s2.final_setup()

if __name__ == '__main__':
pyjd.setup("./public/jQuerySelect2.html")
w = MainWindow()
w.onModuleLoad()
pyjd.run()
Loading