jqmobile_helpers 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/Gemfile +13 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +6 -0
  4. data/Rakefile +29 -0
  5. data/lib/jqmobile_helpers.rb +1 -0
  6. data/lib/jqmobile_helpers/action_view_extensions/form_helper.rb +54 -0
  7. data/lib/jqmobile_helpers/buttons_helper.rb +639 -0
  8. data/lib/jqmobile_helpers/form_builder.rb +301 -0
  9. data/lib/jqmobile_helpers/list_views_helper.rb +326 -0
  10. data/lib/jqmobile_helpers/railtie.rb +23 -0
  11. data/lib/jqmobile_helpers/toolbars_helper.rb +115 -0
  12. data/rdoc/JqmobileHelpers.html +185 -0
  13. data/rdoc/JqmobileHelpers/ActionViewExtensions.html +160 -0
  14. data/rdoc/JqmobileHelpers/ActionViewExtensions/FormHelper.html +231 -0
  15. data/rdoc/JqmobileHelpers/ButtonsHelper.html +1502 -0
  16. data/rdoc/JqmobileHelpers/FormBuilder.html +816 -0
  17. data/rdoc/JqmobileHelpers/ListViewsHelper.html +952 -0
  18. data/rdoc/JqmobileHelpers/Railtie.html +177 -0
  19. data/rdoc/JqmobileHelpers/ToolbarsHelper.html +416 -0
  20. data/rdoc/README_rdoc.html +109 -0
  21. data/rdoc/created.rid +9 -0
  22. data/rdoc/index.html +180 -0
  23. data/rdoc/js/darkfish.js +116 -0
  24. data/rdoc/js/jquery.js +32 -0
  25. data/rdoc/js/quicksearch.js +114 -0
  26. data/rdoc/js/thickbox-compressed.js +10 -0
  27. data/rdoc/lib/jqmobile_helpers/action_view_extensions/form_helper_rb.html +52 -0
  28. data/rdoc/lib/jqmobile_helpers/buttons_helper_rb.html +52 -0
  29. data/rdoc/lib/jqmobile_helpers/form_builder_rb.html +52 -0
  30. data/rdoc/lib/jqmobile_helpers/list_views_helper_rb.html +52 -0
  31. data/rdoc/lib/jqmobile_helpers/railtie_rb.html +62 -0
  32. data/rdoc/lib/jqmobile_helpers/toolbars_helper_rb.html +52 -0
  33. data/rdoc/lib/jqmobile_helpers_rb.html +54 -0
  34. data/rdoc/rdoc.css +706 -0
  35. data/test/buttons_helper_test.rb +112 -0
  36. data/test/dummy/Rakefile +7 -0
  37. data/test/dummy/app/controllers/application_controller.rb +3 -0
  38. data/test/dummy/app/controllers/buttons_controller.rb +9 -0
  39. data/test/dummy/app/controllers/forms_controller.rb +71 -0
  40. data/test/dummy/app/controllers/posts_controller.rb +83 -0
  41. data/test/dummy/app/controllers/toolbars_controller.rb +16 -0
  42. data/test/dummy/app/helpers/application_helper.rb +2 -0
  43. data/test/dummy/app/helpers/posts_helper.rb +2 -0
  44. data/test/dummy/app/helpers/toolbars_helper.rb +2 -0
  45. data/test/dummy/app/models/post.rb +2 -0
  46. data/test/dummy/app/models/toolbar.rb +2 -0
  47. data/test/dummy/app/views/buttons/index.html.erb +168 -0
  48. data/test/dummy/app/views/forms/_form.html.erb +20 -0
  49. data/test/dummy/app/views/forms/edit.html.erb +6 -0
  50. data/test/dummy/app/views/forms/index.html.erb +7 -0
  51. data/test/dummy/app/views/forms/new.html.erb +5 -0
  52. data/test/dummy/app/views/forms/show.html.erb +24 -0
  53. data/test/dummy/app/views/layouts/application.html.erb +49 -0
  54. data/test/dummy/app/views/posts/_form.html.erb +29 -0
  55. data/test/dummy/app/views/posts/edit.html.erb +6 -0
  56. data/test/dummy/app/views/posts/index.html.erb +128 -0
  57. data/test/dummy/app/views/posts/new.html.erb +5 -0
  58. data/test/dummy/app/views/posts/show.html.erb +24 -0
  59. data/test/dummy/app/views/toolbars/index.html.erb +25 -0
  60. data/test/dummy/config.ru +4 -0
  61. data/test/dummy/config/application.rb +45 -0
  62. data/test/dummy/config/boot.rb +10 -0
  63. data/test/dummy/config/database.yml +22 -0
  64. data/test/dummy/config/environment.rb +5 -0
  65. data/test/dummy/config/environments/development.rb +26 -0
  66. data/test/dummy/config/environments/production.rb +49 -0
  67. data/test/dummy/config/environments/test.rb +35 -0
  68. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  69. data/test/dummy/config/initializers/inflections.rb +10 -0
  70. data/test/dummy/config/initializers/mime_types.rb +5 -0
  71. data/test/dummy/config/initializers/secret_token.rb +7 -0
  72. data/test/dummy/config/initializers/session_store.rb +8 -0
  73. data/test/dummy/config/locales/en.yml +5 -0
  74. data/test/dummy/config/routes.rb +69 -0
  75. data/test/dummy/db/development.sqlite3 +0 -0
  76. data/test/dummy/db/migrate/20110218095442_create_posts.rb +15 -0
  77. data/test/dummy/db/migrate/20110223031713_create_toolbars.rb +12 -0
  78. data/test/dummy/db/schema.rb +29 -0
  79. data/test/dummy/db/test.sqlite3 +0 -0
  80. data/test/dummy/log/development.log +7446 -0
  81. data/test/dummy/log/production.log +0 -0
  82. data/test/dummy/log/server.log +0 -0
  83. data/test/dummy/log/test.log +2278 -0
  84. data/test/dummy/public/404.html +26 -0
  85. data/test/dummy/public/422.html +26 -0
  86. data/test/dummy/public/500.html +26 -0
  87. data/test/dummy/public/favicon.ico +0 -0
  88. data/test/dummy/public/images/ajax-loader.png +0 -0
  89. data/test/dummy/public/images/form-check-off.png +0 -0
  90. data/test/dummy/public/images/form-check-on.png +0 -0
  91. data/test/dummy/public/images/form-radio-off.png +0 -0
  92. data/test/dummy/public/images/form-radio-on.png +0 -0
  93. data/test/dummy/public/images/icon-search-black.png +0 -0
  94. data/test/dummy/public/images/icons-18-black.png +0 -0
  95. data/test/dummy/public/images/icons-18-white.png +0 -0
  96. data/test/dummy/public/images/icons-36-black.png +0 -0
  97. data/test/dummy/public/images/icons-36-white.png +0 -0
  98. data/test/dummy/public/javascripts/application.js +2 -0
  99. data/test/dummy/public/javascripts/jquery-1.5.min.js +8176 -0
  100. data/test/dummy/public/javascripts/jquery-ui-1.8.9.custom.min.js +781 -0
  101. data/test/dummy/public/javascripts/jquery.mobile-1.0a3.min.js +121 -0
  102. data/test/dummy/public/javascripts/rails.js +175 -0
  103. data/test/dummy/public/stylesheets/images/ajax-loader.png +0 -0
  104. data/test/dummy/public/stylesheets/images/form-check-off.png +0 -0
  105. data/test/dummy/public/stylesheets/images/form-check-on.png +0 -0
  106. data/test/dummy/public/stylesheets/images/form-radio-off.png +0 -0
  107. data/test/dummy/public/stylesheets/images/form-radio-on.png +0 -0
  108. data/test/dummy/public/stylesheets/images/icon-search-black.png +0 -0
  109. data/test/dummy/public/stylesheets/images/icons-18-black.png +0 -0
  110. data/test/dummy/public/stylesheets/images/icons-18-white.png +0 -0
  111. data/test/dummy/public/stylesheets/images/icons-36-black.png +0 -0
  112. data/test/dummy/public/stylesheets/images/icons-36-white.png +0 -0
  113. data/test/dummy/public/stylesheets/jquery-ui-1.8.9.custom.css +573 -0
  114. data/test/dummy/public/stylesheets/jquery.mobile-1.0a3.min.css +16 -0
  115. data/test/dummy/public/stylesheets/scaffold.css +56 -0
  116. data/test/dummy/script/rails +6 -0
  117. data/test/dummy/tmp/pids/server.pid +1 -0
  118. data/test/form_helper_test.rb +13 -0
  119. data/test/integration/navigation_test.rb +7 -0
  120. data/test/list_views_helper_test.rb +65 -0
  121. data/test/support/integration_case.rb +5 -0
  122. data/test/support/misc_helpers.rb +18 -0
  123. data/test/support/mock_controller.rb +15 -0
  124. data/test/support/mock_response.rb +14 -0
  125. data/test/support/models.rb +135 -0
  126. data/test/test_helper.rb +92 -0
  127. data/test/toolbars_helper_test.rb +21 -0
  128. metadata +182 -0
@@ -0,0 +1,20 @@
1
+ <%= jq_form_for(@post, :url => forms_path) do |f| %>
2
+
3
+ <% if @post.errors.any? %>
4
+ <div id="error_explanation">
5
+ <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
6
+
7
+ <ul>
8
+ <% @post.errors.full_messages.each do |msg| %>
9
+ <li><%= msg %></li>
10
+ <% end %>
11
+ </ul>
12
+ </div>
13
+ <% end %>
14
+
15
+ <%= f.text_field :name %>
16
+
17
+ <%= f.text_field :title %>
18
+ <%= f.text_area :content %>
19
+ <%= f.submit %>
20
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing post</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @post %> |
6
+ <%= link_to 'Back', forms_path %>
@@ -0,0 +1,7 @@
1
+ <% content_for :header do %>
2
+ <h1>Forms Helper</h1>
3
+ <% end %>
4
+
5
+ <%= basic_list @posts.map{|x| link_to(x.title, form_path(x))} %>
6
+
7
+ <%= link_to 'New Post', new_form_path %>
@@ -0,0 +1,5 @@
1
+ <h1>New post</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', forms_path %>
@@ -0,0 +1,24 @@
1
+ <% content_for :header do %>
2
+ <h1>List View Helper</h1>
3
+ <% end %>
4
+
5
+ <p id="notice"><%= notice %></p>
6
+
7
+ <p>
8
+ <b>Name:</b>
9
+ <%= @post.name %>
10
+ </p>
11
+
12
+ <p>
13
+ <b>Title:</b>
14
+ <%= @post.title %>
15
+ </p>
16
+
17
+ <p>
18
+ <b>Content:</b>
19
+ <%= @post.content %>
20
+ </p>
21
+
22
+
23
+ <%= back_split_button "Back", posts_path %>
24
+ <%= link_to "Edit", edit_post_path(@post) %>
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag "jquery.mobile-1.0a3.min" %>
6
+ <%= javascript_include_tag "jquery-1.5.min" %>
7
+ <script type="text/javascript" charset="utf-8">
8
+ $(document).bind("mobileinit", function(){
9
+ $.mobile.ajaxFormsEnabled = false;
10
+ });
11
+ </script>>
12
+ <%= javascript_include_tag "jquery.mobile-1.0a3.min" %>
13
+ <%= csrf_meta_tag %>
14
+ </head>
15
+
16
+ <body>
17
+
18
+ <div data-role="page">
19
+
20
+ <!-- header part -->
21
+ <div data-role="header" data-position="fixed" data-backbtn="true">
22
+
23
+ <%= header_toolbar_title('EW CORE') %>
24
+ <%= header_toolbar_link('Toolbar',toolbars_path, {'data-icon'=>"gear", 'data-iconpos' => 'notext', 'data-theme' => 'c'}) %>
25
+ <%= header_toolbar_link('Homies',root_path, {'data-icon'=>"check", 'data-theme'=>'b'}) %>
26
+
27
+ <% link_collection = [
28
+ navbar_link('list view',root_path,{'data-icon' => 'gear','data-theme' => 'c', 'class' => 'ui-btn-active'}),
29
+ navbar_link('button view',buttons_path,{'data-icon' => 'gear'}),
30
+ navbar_link('toolbar view',toolbars_path,{'data-icon' => 'home'}),
31
+ navbar_link('form helpers', forms_path)] %>
32
+
33
+ <%= navbar_bar(link_collection) %>
34
+
35
+ </div>
36
+
37
+ <!-- end header part -->
38
+
39
+ <div data-role="content">
40
+ <%= yield %>
41
+ </div>
42
+
43
+ <div data-role="footer">
44
+ <h4>Page Footer</h4>
45
+ </div><!-- /footer -->
46
+
47
+ </div>
48
+ </body>
49
+ </html>
@@ -0,0 +1,29 @@
1
+ <%= form_for(@post) do |f| %>
2
+ <% if @post.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @post.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= f.label :name %><br />
16
+ <%= f.text_field :name %>
17
+ </div>
18
+ <div class="field">
19
+ <%= f.label :title %><br />
20
+ <%= f.text_field :title %>
21
+ </div>
22
+ <div class="field">
23
+ <%= f.label :content %><br />
24
+ <%= f.text_area :content %>
25
+ </div>
26
+ <div class="actions">
27
+ <%= f.submit %>
28
+ </div>
29
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing post</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @post %> |
6
+ <%= link_to 'Back', posts_path %>
@@ -0,0 +1,128 @@
1
+ <% content_for :header do %>
2
+ <h1>List View Helper</h1>
3
+ <% end %>
4
+
5
+ <h1>List View Helper</h1>
6
+
7
+ <h2>Read only list</h2>
8
+
9
+ <%= basic_list @posts.map{|x| x.title}, {'data-theme'=>'b'} %>
10
+
11
+ <br/>
12
+
13
+ <h2>Basic linked list</h2>
14
+
15
+ <%= basic_list @posts.map{|x| link_to(x.title, post_path(x))} %>
16
+
17
+ <br />
18
+
19
+
20
+ <h2>Basic linked list</h2>
21
+
22
+ <p>data-inset='true' is default</p>
23
+ <p>data-theme='c' is jquery-mobile default</p>
24
+ <%= basic_list @posts.map{|x| link_to(x.title, post_path(x))} %>
25
+
26
+ <br /><br />
27
+
28
+ <h2>Nested List</h2>
29
+
30
+ <%= nested_list @posts.map{|x| link_to(x.title, post_path(x))} %>
31
+
32
+ <br /><br />
33
+
34
+ <h2>Basic linked list inset option false, data-theme = 'a'</h2>
35
+
36
+ <%= basic_list(@posts.map{|x| link_to(x.title, post_path(x))}, {'data-inset' => 'false', 'data-theme' => 'a'}) %>
37
+
38
+ <br />
39
+
40
+ <h2>Basic numbered list</h2>
41
+
42
+ <%= numbered_list(@posts.map{|x| link_to(x.title, post_path(x))}) %>
43
+ <br /><br />
44
+
45
+ <h2>Split Button List</h2>
46
+
47
+ <% @posts.each do |post| %>
48
+ <%= split_button_list(post.name, post_path(post))%>
49
+ <% end %>
50
+
51
+
52
+ <h2>Count Bubble List</h2>
53
+
54
+ <%= count_bubble(@posts.map do |x| [x.title, link_to(x.title, post_path(x))] end)%>
55
+
56
+
57
+ <br /><br />
58
+
59
+ <h2>Thumbnails List</h2>
60
+
61
+ <%= thumbnail_list(@posts.collect do |x|
62
+ [image_tag('https://github.com/jquery/jquery-mobile/raw/master/docs/lists/images/album-bb.jpg'),
63
+ link_to(x.title, post_path(x)),
64
+ x.title]
65
+ end) %>
66
+
67
+
68
+ <br /><br />
69
+
70
+ <h2>Icon List</h2>
71
+
72
+ <%= icon_list(@posts.map do |x|
73
+ [image_tag('https://github.com/jquery/jquery-mobile/blob/master/docs/lists/images/gb.png', :class => "ui-li-icon"),
74
+ link_to(x.title, post_path(x))]
75
+ end) %>
76
+
77
+
78
+ <br /><br />
79
+
80
+ <h2>Search Filter List</h2>
81
+
82
+ <%= search_filter_list(@posts.map{|x| link_to(x.title, post_path(x))}) %>
83
+
84
+ <br /><br />
85
+
86
+ <h2>List Performance Test</h2>
87
+
88
+ <%= search_filter_list(@posts.map{|x| link_to(x.title, post_path(x))}, {'data-theme' => "d"}) %>
89
+
90
+ <br /><br />
91
+
92
+
93
+ <h2>List Formatting</h2>
94
+
95
+
96
+ <%= list_formatting @posts.map{|x| x.title} %>
97
+
98
+
99
+ <br /><br />
100
+
101
+ <h2>List Divider</h2>
102
+
103
+ <%= list_divider @posts.map{|x| x.title[0]}.sort, @posts.map{|c| c.title} %>
104
+
105
+ <br /><br />
106
+
107
+ <h2>Inset linked list</h2>
108
+ <p>data-inset='true' is default</p>
109
+ <p>data-theme='c' is default</p>
110
+ <%= inset_list @posts.map{|x| link_to(x.title, post_path(x))} %>
111
+ <br />
112
+ <p>Set data-theme='b'</p>
113
+ <%= inset_list @posts.map{|x| link_to(x.title, post_path(x))}, {'data-theme' => "b"} %>
114
+ <br /><br />
115
+
116
+ <h2>Inset Order linked list</h2>
117
+ <p>data-inset='true' is default</p>
118
+ <p>data-theme='c' is default</p>
119
+ <%= ol_inset_list @posts.map{|x| link_to(x.title, post_path(x))} %>
120
+ <br />
121
+ <p>Set data-theme='b'</p>
122
+ <%= ol_inset_list @posts.map{|x| link_to(x.title, post_path(x))}, {'data-theme' => "a"} %>
123
+ <br /><br />
124
+
125
+
126
+ <br /><br />
127
+ <%= link_to 'New Post', new_post_path %>
128
+
@@ -0,0 +1,5 @@
1
+ <h1>New post</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', posts_path %>
@@ -0,0 +1,24 @@
1
+ <% content_for :header do %>
2
+ <h1>List View Helper</h1>
3
+ <% end %>
4
+
5
+ <p id="notice"><%= notice %></p>
6
+
7
+ <p>
8
+ <b>Name:</b>
9
+ <%= @post.name %>
10
+ </p>
11
+
12
+ <p>
13
+ <b>Title:</b>
14
+ <%= @post.title %>
15
+ </p>
16
+
17
+ <p>
18
+ <b>Content:</b>
19
+ <%= @post.content %>
20
+ </p>
21
+
22
+
23
+ <%= back_split_button "Back", posts_path %>
24
+ <%= button_link "Edit", edit_post_path(@post), {'data-rel'=> 'front'} %>
@@ -0,0 +1,25 @@
1
+
2
+ <p>navbar link</p>
3
+
4
+ <p>
5
+ <ul>
6
+ <li>list view link options = 'data-icon' => 'gear','data-theme' => 'c', 'class' => 'ui-btn-active'</li>
7
+ <li>button view link options = 'data-icon' => 'gear'</li>
8
+ <li>toolbar view link options = 'data-icon' => 'home'</li>
9
+ </ul>
10
+ </p>
11
+
12
+ <p>
13
+ <ul>
14
+ <li>div data-role="header" set with data-position="fixed" && data-backbtn="true"</li>
15
+ <li>
16
+ <ul>
17
+ <li>toolbar link on the left side set with data-icon="gear", data-iconpos="notext"</li>
18
+ <li>toolbar link on the right side set with data-theme="b", data-icon="check"</li>
19
+ <li></li>
20
+ </ul>
21
+ </li>
22
+ </ul>
23
+ </p>
24
+
25
+
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "active_model/railtie"
4
+ require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_view/railtie"
7
+ require "action_mailer/railtie"
8
+
9
+ Bundler.require
10
+ require "jqmobile_helpers"
11
+
12
+ module Dummy
13
+ class Application < Rails::Application
14
+ # Settings in config/environments/* take precedence over those specified here.
15
+ # Application configuration should go into files in config/initializers
16
+ # -- all .rb files in that directory are automatically loaded.
17
+
18
+ # Custom directories with classes and modules you want to be autoloadable.
19
+ # config.autoload_paths += %W(#{config.root}/extras)
20
+
21
+ # Only load the plugins named here, in the order given (default is alphabetical).
22
+ # :all can be used as a placeholder for all plugins not explicitly named.
23
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
+
25
+ # Activate observers that should always be running.
26
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
+
28
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30
+ # config.time_zone = 'Central Time (US & Canada)'
31
+
32
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34
+ # config.i18n.default_locale = :de
35
+
36
+ # JavaScript files you want as :defaults (application.js is always included).
37
+ # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
38
+
39
+ # Configure the default encoding used in templates for Ruby 1.9.
40
+ config.encoding = "utf-8"
41
+
42
+ # Configure sensitive parameters which will be filtered from the log file.
43
+ config.filter_parameters += [:password]
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ gemfile = File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ if File.exist?(gemfile)
5
+ ENV['BUNDLE_GEMFILE'] = gemfile
6
+ require 'bundler'
7
+ Bundler.setup
8
+ end
9
+
10
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,22 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3-ruby (not necessary on OS X Leopard)
3
+ development:
4
+ adapter: sqlite3
5
+ database: db/development.sqlite3
6
+ pool: 5
7
+ timeout: 5000
8
+
9
+ # Warning: The database defined as "test" will be erased and
10
+ # re-generated from your development database when you run "rake".
11
+ # Do not set this db to the same as development or production.
12
+ test:
13
+ adapter: sqlite3
14
+ database: db/test.sqlite3
15
+ pool: 5
16
+ timeout: 5000
17
+
18
+ production:
19
+ adapter: sqlite3
20
+ database: db/production.sqlite3
21
+ pool: 5
22
+ timeout: 5000
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Dummy::Application.initialize!