iruby 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ begin
2
+ require 'erector'
3
+ rescue LoadError
4
+ raise LoadError, <<-ERROR.gsub(/\s+/,' ')
5
+ IRuby::Input requires the erector gem.
6
+ `gem install erector` or add `gem 'erector'`
7
+ it to your Gemfile to continue.
8
+ ERROR
9
+ end
10
+
11
+ require 'iruby/input/builder'
12
+ require 'iruby/input/widget'
13
+ require 'iruby/input/form'
14
+ require 'iruby/input/label'
15
+ require 'iruby/input/field'
16
+ require 'iruby/input/popup'
17
+ require 'iruby/input/button'
18
+ require 'iruby/input/cancel'
19
+ require 'iruby/input/file'
20
+ require 'iruby/input/select'
21
+ require 'iruby/input/checkbox'
22
+ require 'iruby/input/radio'
23
+ require 'iruby/input/textarea'
24
+ require 'iruby/input/date'
@@ -0,0 +1,67 @@
1
+ module IRuby
2
+ module Input
3
+ class Builder
4
+ attr_reader :fields, :buttons
5
+
6
+ def initialize &block
7
+ @processors = {}
8
+ @fields, @buttons = [], []
9
+ instance_eval &block
10
+ end
11
+
12
+ def add_field field
13
+ @fields << field
14
+ end
15
+
16
+ def add_button button
17
+ # see bit.ly/1Tsv6x4
18
+ @buttons.unshift button
19
+ end
20
+
21
+ def html &block
22
+ add_field Class.new(Widget) {
23
+ define_method(:widget_html) { instance_eval &block }
24
+ }.new
25
+ end
26
+
27
+ def text string
28
+ html { label string }
29
+ end
30
+
31
+ def password key='password', **params
32
+ input key, **params.merge(type: 'password')
33
+ end
34
+
35
+ def process_result result
36
+ unless result.nil?
37
+ result.each_with_object({}) do |(k,v),h|
38
+ if @processors.has_key? k
39
+ @processors[k].call h, k, v
40
+ else
41
+ h[k.to_sym] = v
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def process key, &block
50
+ @processors[key.to_s] = block
51
+ end
52
+
53
+ def unique_key key
54
+ @keys ||= []
55
+
56
+ if @keys.include? key
57
+ (2..Float::INFINITY).each do |i|
58
+ test = "#{key}#{i}"
59
+ break key = test unless @keys.include? test
60
+ end
61
+ end
62
+
63
+ @keys << key; key
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,47 @@
1
+ module IRuby
2
+ module Input
3
+ # extend the label class for the to_label helper
4
+ class Button < Label
5
+ needs color: :blue, js_class: 'iruby-button'
6
+
7
+ COLORS = {
8
+ blue: 'primary',
9
+ gray: 'secondary',
10
+ green: 'success',
11
+ aqua: 'info',
12
+ orange: 'warning',
13
+ red: 'danger',
14
+ none: 'link'
15
+ }
16
+
17
+ COLORS.default = 'primary'
18
+
19
+ builder :button do |key='done', **params|
20
+ params[:key] = unique_key(key)
21
+ add_button Button.new(**params)
22
+ end
23
+
24
+ def widget_css
25
+ ".#{@js_class} { margin-left: 5px; }"
26
+ end
27
+
28
+ def widget_js
29
+ <<-JS
30
+ $('.iruby-button').click(function(){
31
+ $(this).data('iruby-value', true);
32
+ $('#iruby-form').submit();
33
+ });
34
+ JS
35
+ end
36
+
37
+ def widget_html
38
+ button(
39
+ @label || to_label(@key),
40
+ type: 'button',
41
+ :'data-iruby-key' => @key,
42
+ class: "btn btn-#{COLORS[@color]} pull-right #{@js_class}"
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ module IRuby
2
+ module Input
3
+ class Cancel < Widget
4
+ needs :label
5
+
6
+ builder :cancel do |label='Cancel'|
7
+ add_button Cancel.new(label: label)
8
+ end
9
+
10
+ def widget_css
11
+ ".iruby-cancel { margin-left: 5px; }"
12
+ end
13
+
14
+ def widget_js
15
+ <<-JS
16
+ $('.iruby-cancel').click(function(){
17
+ $('#iruby-form').remove();
18
+ });
19
+ JS
20
+ end
21
+
22
+ def widget_html
23
+ button(
24
+ @label,
25
+ type: 'button',
26
+ :'data-dismiss' => 'modal',
27
+ class: "btn btn-danger pull-right iruby-cancel"
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ module IRuby
2
+ module Input
3
+ class Checkbox < Label
4
+ needs :options
5
+
6
+ builder :checkbox do |*args, **params|
7
+ key = :checkbox
8
+ key, *args = args if args.first.is_a? Symbol
9
+
10
+ params[:key] = unique_key(key)
11
+ params[:options] = args
12
+ add_field Checkbox.new(**params)
13
+ end
14
+
15
+ def widget_css
16
+ '.iruby-checkbox-container { margin-left: 10px; }'
17
+ end
18
+
19
+ def widget_js
20
+ <<-JS
21
+ $('.iruby-checkbox input').change(function(){
22
+ var parent = $(this).closest('.iruby-checkbox');
23
+ $(parent).data('iruby-value', []);
24
+
25
+ $(parent).find(':checked').each(function(){
26
+ $(parent).data('iruby-value').push($(this).val());
27
+ });
28
+
29
+ if ($(parent).data('iruby-value').length == 0) {
30
+ $(parent).data('iruby-value', null);
31
+ }
32
+ });
33
+ JS
34
+ end
35
+
36
+ def widget_html
37
+ params = {
38
+ :'data-iruby-key' => @key,
39
+ class: 'iruby-checkbox form-control'
40
+ }
41
+ widget_label do
42
+ div **params do
43
+ @options.each do |option|
44
+ label class: 'checkbox-inline' do
45
+ input(
46
+ name: @key, value: option, type: 'checkbox'
47
+ )
48
+ text option
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ module IRuby
2
+ module Input
3
+ class Date < Field
4
+ needs js_class: 'iruby-date'
5
+
6
+ builder :date do |key='date', **params|
7
+ params[:key] = unique_key key
8
+ add_field Date.new(**params)
9
+ end
10
+
11
+ def widget_css
12
+ '#ui-datepicker-div { z-index: 2000; }'
13
+ end
14
+
15
+ def widget_js
16
+ <<-JS
17
+ $('.iruby-date').datepicker({
18
+ onClose: function(date) {
19
+ $('.iruby-date').data('iruby-value', date);
20
+ }
21
+ });
22
+ JS
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module IRuby
2
+ module Input
3
+ class Field < Label
4
+ needs :type => 'text', js_class: 'iruby-field'
5
+
6
+ builder :input do |key='input', **params|
7
+ params[:key] = unique_key key
8
+ add_field Field.new(**params)
9
+ end
10
+
11
+ def widget_js
12
+ <<-JS
13
+ $('.iruby-field').keyup(function() {
14
+ $(this).data('iruby-value', $(this).val());
15
+ });
16
+ JS
17
+ end
18
+
19
+ def widget_html
20
+ widget_label do
21
+ input(
22
+ type: @type,
23
+ :'data-iruby-key' => @key,
24
+ class: "form-control #{@js_class}"
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,57 @@
1
+ require 'data_uri'
2
+
3
+ module IRuby
4
+ module Input
5
+ class File < Label
6
+ builder :file do |key='file', **params|
7
+ key = unique_key key
8
+ add_field File.new(key: key, **params)
9
+
10
+ # tell the builder to process files differently
11
+ process key do |result,key,value|
12
+ uri = URI::Data.new value['data']
13
+
14
+ # get rid of Chrome's silly path
15
+ name = value['name'].sub('C:\\fakepath\\','')
16
+
17
+ result[key.to_sym] = {
18
+ name: name,
19
+ data: uri.data,
20
+ content_type: uri.content_type
21
+ }
22
+ end
23
+ end
24
+
25
+ def widget_js
26
+ <<-JS
27
+ $('.iruby-file').change(function() {
28
+ var input = $(this);
29
+
30
+ $.grep($(this).prop('files'), function(file) {
31
+ var reader = new FileReader();
32
+
33
+ reader.addEventListener("load", function(event) {
34
+ input.data('iruby-value', {
35
+ name: input.val(),
36
+ data: event.target.result
37
+ });
38
+ });
39
+
40
+ reader.readAsDataURL(file);
41
+ });
42
+ });
43
+ JS
44
+ end
45
+
46
+ def widget_html
47
+ widget_label do
48
+ input(
49
+ type: 'file',
50
+ :'data-iruby-key' => @key,
51
+ class: 'form-control iruby-file'
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,77 @@
1
+ require 'securerandom'
2
+
3
+ module IRuby
4
+ module Input
5
+ class InputForm < Widget
6
+ needs :fields, buttons: []
7
+
8
+ def widget_js
9
+ javascript = <<-JS
10
+ var remove = function () {
11
+ Jupyter.notebook.kernel.send_input_reply(
12
+ JSON.stringify({
13
+ '#{@id = SecureRandom.uuid}': null
14
+ })
15
+ );
16
+ };
17
+
18
+ $("#iruby-form").on("remove", remove);
19
+
20
+ $('#iruby-form').submit(function() {
21
+ var result = {};
22
+ $(this).off('remove', remove);
23
+
24
+ $('[data-iruby-key]').each(function() {
25
+ if ($(this).data('iruby-key')) {
26
+ var value = $(this).data('iruby-value');
27
+ if (value) {
28
+ result[$(this).data('iruby-key')] = value;
29
+ }
30
+ }
31
+ });
32
+
33
+ Jupyter.notebook.kernel.send_input_reply(
34
+ JSON.stringify({'#{@id}': result})
35
+ );
36
+
37
+ $(this).remove();
38
+ return false;
39
+ });
40
+
41
+ $('#iruby-form').keydown(function(event) {
42
+ if (event.keyCode == 13 && !event.shiftKey) {
43
+ $('#iruby-form').submit();
44
+ } else if (event.keyCode == 27) {
45
+ $('#iruby-form').remove();
46
+ }
47
+ });
48
+ JS
49
+
50
+ widget_join :widget_js, javascript, *@fields, *@buttons
51
+ end
52
+
53
+ def widget_css
54
+ spacing = '#iruby-form > * { margin-bottom: 5px; }'
55
+ widget_join :widget_css, spacing, *@fields, *@buttons
56
+ end
57
+
58
+ def widget_html
59
+ form id: 'iruby-form', class: 'col-md-12' do
60
+ @fields.each {|field| widget field}
61
+ end
62
+ @buttons.each {|button| widget button}
63
+ end
64
+
65
+ def submit
66
+ result = MultiJson.load(Kernel.instance.session.recv_input)
67
+
68
+ unless result.has_key? @id
69
+ submit
70
+ else
71
+ Display.clear_output
72
+ result[@id]
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ module IRuby
2
+ module Input
3
+ class Label < Widget
4
+ needs label: nil
5
+
6
+ def widget_label
7
+ label = @label || to_label(@key)
8
+ div class: 'iruby-label input-group' do
9
+ span label, class: 'input-group-addon'
10
+ yield
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def to_label label
17
+ label.to_s.tr('_',' ').capitalize
18
+ end
19
+ end
20
+ end
21
+ end