iruby 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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