##// END OF EJS Templates
Changed on_submit to use custom messages instead of stateful communcation
Jonathan Frederic -
Show More
@@ -1,161 +1,161 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // StringWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widget"], function(widget_manager){
18 18 var StringWidgetModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
20 20
21 21 var LabelView = IPython.WidgetView.extend({
22 22
23 23 // Called when view is rendered.
24 24 render : function(){
25 25 this.update(); // Set defaults.
26 26 },
27 27
28 28 // Handles: Backend -> Frontend Sync
29 29 // Frontent -> Frontend Sync
30 30 update : function(){
31 31 this.$el.html(this.model.get('value'));
32 32 return IPython.WidgetView.prototype.update.call(this);
33 33 },
34 34
35 35 });
36 36
37 37 widget_manager.register_widget_view('LabelView', LabelView);
38 38
39 39 var TextAreaView = IPython.WidgetView.extend({
40 40
41 41 // Called when view is rendered.
42 42 render : function(){
43 43 this.$el
44 44 .addClass('widget-hbox')
45 45 .html('');
46 46 this.$label = $('<div />')
47 47 .appendTo(this.$el)
48 48 .addClass('widget-hlabel')
49 49 .hide();
50 50 this.$textbox = $('<textarea />')
51 51 .attr('rows', 5)
52 52 .addClass('widget-text')
53 53 .appendTo(this.$el);
54 54 this.$el_to_style = this.$textbox; // Set default element to style
55 55 this.update(); // Set defaults.
56 56 },
57 57
58 58 // Handles: Backend -> Frontend Sync
59 59 // Frontent -> Frontend Sync
60 60 update : function(){
61 61 if (!this.user_invoked_update) {
62 62 this.$textbox.val(this.model.get('value'));
63 63 }
64 64
65 65 if (this.last_scroll_to_bottom == undefined) {
66 66 this.last_scroll_to_bottom = 0;
67 67 }
68 68 if (this.last_scroll_to_bottom < this.model.get('scroll_to_bottoms')) {
69 69 this.last_scroll_to_bottom < this.model.get('scroll_to_bottoms');
70 70 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
71 71 }
72 72
73 73 var disabled = this.model.get('disabled');
74 74 this.$textbox.prop('disabled', disabled);
75 75
76 76 var description = this.model.get('description');
77 77 if (description.length == 0) {
78 78 this.$label.hide();
79 79 } else {
80 80 this.$label.html(description);
81 81 this.$label.show();
82 82 }
83 83 return IPython.WidgetView.prototype.update.call(this);
84 84 },
85 85
86 86 events: {"keyup textarea" : "handleChanging",
87 87 "paste textarea" : "handleChanging",
88 88 "cut textarea" : "handleChanging"},
89 89
90 90 // Handles and validates user input.
91 91 handleChanging: function(e) {
92 92 this.user_invoked_update = true;
93 93 this.model.set('value', e.target.value);
94 94 this.model.update_other_views(this);
95 95 this.user_invoked_update = false;
96 96 },
97 97 });
98 98
99 99 widget_manager.register_widget_view('TextAreaView', TextAreaView);
100 100
101 101 var TextBoxView = IPython.WidgetView.extend({
102 102
103 103 // Called when view is rendered.
104 104 render : function(){
105 105 this.$el
106 106 .addClass('widget-hbox-single')
107 107 .html('');
108 108 this.$label = $('<div />')
109 109 .addClass('widget-hlabel')
110 110 .appendTo(this.$el)
111 111 .hide();
112 112 this.$textbox = $('<input type="text" />')
113 113 .addClass('input')
114 114 .addClass('widget-text')
115 115 .appendTo(this.$el);
116 116 this.$el_to_style = this.$textbox; // Set default element to style
117 117 this.update(); // Set defaults.
118 118 },
119 119
120 120 // Handles: Backend -> Frontend Sync
121 121 // Frontent -> Frontend Sync
122 122 update : function(){
123 123 if (this.$textbox.val() != this.model.get('value')) {
124 124 this.$textbox.val(this.model.get('value'));
125 125 }
126 126
127 127 var disabled = this.model.get('disabled');
128 128 this.$textbox.prop('disabled', disabled);
129 129
130 130 var description = this.model.get('description');
131 131 if (description.length == 0) {
132 132 this.$label.hide();
133 133 } else {
134 134 this.$label.html(description);
135 135 this.$label.show();
136 136 }
137 137 return IPython.WidgetView.prototype.update.call(this);
138 138 },
139 139
140 140 events: {"keyup input" : "handleChanging",
141 141 "paste input" : "handleChanging",
142 142 "cut input" : "handleChanging",
143 143 "keypress input" : "handleKeypress"},
144 144
145 145 // Handles and validates user input.
146 146 handleChanging: function(e) {
147 147 this.model.set('value', e.target.value);
148 148 this.model.update_other_views(this);
149 149 },
150 150
151 151 // Handles text submition
152 152 handleKeypress: function(e) {
153 153 if (e.keyCode == 13) { // Return key
154 this.model.set('submits', this.model.get('submits') + 1);
155 this.model.update_other_views(this);
154 this.model.last_modified_view = this; // For callbacks.
155 this.model.send({event: 'submit'});
156 156 }
157 157 },
158 158 });
159 159
160 160 widget_manager.register_widget_view('TextBoxView', TextBoxView);
161 161 });
@@ -1,84 +1,112 b''
1 1 """StringWidget class.
2 2
3 3 Represents a unicode string using a widget.
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 import inspect
17 17 import types
18 18
19 19 from .widget import Widget
20 20 from IPython.utils.traitlets import Unicode, Bool, List, Int
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Classes
24 24 #-----------------------------------------------------------------------------
25 25 class StringWidget(Widget):
26 26 target_name = Unicode('StringWidgetModel')
27 27 default_view_name = Unicode('TextBoxView')
28 28
29 29 # Keys
30 _keys = ['value', 'disabled', 'description', 'submits', 'scroll_to_bottoms']
30 _keys = ['value', 'disabled', 'description', 'scroll_to_bottoms']
31 31 value = Unicode(help="String value")
32 32 disabled = Bool(False, help="Enable or disable user changes")
33 33 description = Unicode(help="Description of the value this widget represents")
34 submits = Int(0, help="Used to capture and fire submission ")
35 34 scroll_to_bottoms = Int(0, help="Used to scroll a TextAreaView to the bottom")
36 35
37 36
38 37 def __init__(self, **kwargs):
39 38 super(StringWidget, self).__init__(**kwargs)
40 self._submission_callbacks = []
39 self._submission_callbacks = []
40 self.on_msg(self._handle_string_msg)
41 41
42 42
43 43 def scroll_to_bottom(self):
44 44 self.scroll_to_bottoms += 1
45 45
46 46
47 def on_click(self, callback, remove=False):
48 """Register a callback to execute when the button is clicked. The
49 callback can either accept no parameters or one sender parameter:
50 - callback()
51 - callback(sender)
52 If the callback has a sender parameter, the ButtonWidget instance that
53 called the callback will be passed into the method as the sender.
54
55 Parameters
56 ----------
57 remove : bool (optional)
58 Set to true to remove the callback from the list of callbacks."""
59 if remove:
60 self._click_handlers.remove(callback)
61 elif not callback in self._click_handlers:
62 self._click_handlers.append(callback)
63
64
65 def _handle_string_msg(self, content):
66 """Handle a msg from the front-end
67
68 Parameters
69 ----------
70 content: dict
71 Content of the msg."""
72 if 'event' in content and content['event'] == 'submit':
73 self._handle_submit()
74
75
47 76 def on_submit(self, callback, remove=False):
48 77 """Register a callback to handle text submission (triggered when the
49 78 user clicks enter).
50 79
51 80 Parameters
52 81 callback: Method handle
53 82 Function to be called when the text has been submitted. Function
54 83 can have two possible signatures:
55 84 callback()
56 85 callback(sender)
57 86 remove: bool (optional)
58 87 Whether or not to unregister the callback"""
59 88 if remove and callback in self._submission_callbacks:
60 89 self._submission_callbacks.remove(callback)
61 90 elif not remove and not callback in self._submission_callbacks:
62 91 self._submission_callbacks.append(callback)
63 92
64 93
65 def _submits_changed(self, name, old_value, new_value):
94 def _handle_submit(self):
66 95 """Handles when a string widget view is submitted."""
67 if new_value > old_value:
68 for handler in self._submission_callbacks:
69 if callable(handler):
70 argspec = inspect.getargspec(handler)
71 nargs = len(argspec[0])
72
73 # Bound methods have an additional 'self' argument
74 if isinstance(handler, types.MethodType):
75 nargs -= 1
76
77 # Call the callback
78 if nargs == 0:
79 handler()
80 elif nargs == 1:
81 handler(self)
82 else:
83 raise TypeError('StringWidget submit callback must ' \
84 'accept 0 or 1 arguments.')
96 for handler in self._submission_callbacks:
97 if callable(handler):
98 argspec = inspect.getargspec(handler)
99 nargs = len(argspec[0])
100
101 # Bound methods have an additional 'self' argument
102 if isinstance(handler, types.MethodType):
103 nargs -= 1
104
105 # Call the callback
106 if nargs == 0:
107 handler()
108 elif nargs == 1:
109 handler(self)
110 else:
111 raise TypeError('StringWidget submit callback must ' \
112 'accept 0 or 1 arguments.')
General Comments 0
You need to be logged in to leave comments. Login now