Commit 90efe3ca9da72beb3c46a6e347253a5bedd94c2a
Committed by
Joenio Costa
1 parent
2836c18c
Exists in
master
and in
29 other branches
Enhancing edition of product
Fixing categories selection and fixing width of sideboxes in leftbar and rightbar templates Added themes to jquery-ui (ActionItem1392)
Showing
88 changed files
with
2905 additions
and
196 deletions
Show diff stats
app/controllers/my_profile/manage_products_controller.rb
1 | 1 | class ManageProductsController < ApplicationController |
2 | 2 | needs_profile |
3 | 3 | |
4 | - protect 'manage_products', :profile | |
4 | + protect 'manage_products', :profile, :except => [:show] | |
5 | 5 | before_filter :check_environment_feature |
6 | + before_filter :login_required, :except => [:show] | |
6 | 7 | |
7 | 8 | protected |
9 | + | |
8 | 10 | def check_environment_feature |
9 | 11 | if profile.environment.enabled?('disable_products_for_enterprises') |
10 | 12 | render_not_found |
... | ... | @@ -13,6 +15,7 @@ class ManageProductsController < ApplicationController |
13 | 15 | end |
14 | 16 | |
15 | 17 | public |
18 | + | |
16 | 19 | def index |
17 | 20 | @products = @profile.products |
18 | 21 | @consumptions = @profile.consumptions |
... | ... | @@ -51,15 +54,34 @@ class ManageProductsController < ApplicationController |
51 | 54 | end |
52 | 55 | |
53 | 56 | def edit |
54 | - @object = @product = @profile.products.find(params[:id]) | |
55 | - @current_category = @product.product_category | |
56 | - @categories = @current_category.nil? ? [] : @current_category.children | |
57 | + @product = @profile.products.find(params[:id]) | |
58 | + field = params[:field] | |
57 | 59 | if request.post? |
58 | - if @product.update_attributes(params[:product]) | |
59 | - flash[:notice] = _('Product succesfully updated') | |
60 | - redirect_back_or_default :action => 'show', :id => @product | |
61 | - else | |
60 | + begin | |
61 | + @product.update_attributes!(params[:product]) | |
62 | + render :partial => "display_#{field}", :locals => {:product => @product} | |
63 | + rescue Exception => e | |
64 | + render :partial => "edit_#{field}", :locals => {:product => @product, :errors => true} | |
65 | + end | |
66 | + else | |
67 | + render :partial => "edit_#{field}", :locals => {:product => @product, :errors => false} | |
68 | + end | |
69 | + end | |
70 | + | |
71 | + def edit_category | |
72 | + @product = @profile.products.find(params[:id]) | |
73 | + @category = @product.product_category | |
74 | + @categories = ProductCategory.top_level_for(environment) | |
75 | + @edit = true | |
76 | + @level = @category.level | |
77 | + if request.post? | |
78 | + begin | |
79 | + @product.update_attributes!(params[:product]) | |
80 | + render :partial => 'shared/redirect_via_javascript', | |
81 | + :locals => { :url => url_for(:controller => 'manage_products', :action => 'show', :id => @product) } | |
82 | + rescue Exception => e | |
62 | 83 | flash[:notice] = _('Could not update the product') |
84 | + render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } | |
63 | 85 | end |
64 | 86 | end |
65 | 87 | end | ... | ... |
app/controllers/public/catalog_controller.rb
1 | 1 | class CatalogController < PublicController |
2 | 2 | needs_profile |
3 | + | |
3 | 4 | before_filter :check_enterprise_and_environment |
4 | 5 | |
5 | 6 | def index |
6 | 7 | @products = @profile.products |
7 | 8 | end |
8 | 9 | |
9 | - def show | |
10 | - @product = @profile.products.find(params[:id]) | |
11 | - end | |
12 | - | |
13 | 10 | protected |
14 | 11 | def check_enterprise_and_environment |
15 | 12 | unless @profile.kind_of?(Enterprise) && !@profile.environment.enabled?('disable_products_for_enterprises') | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -907,7 +907,7 @@ module ApplicationHelper |
907 | 907 | (@section ? @section.title + ' - ' : '') + |
908 | 908 | (@toc ? _('Online Manual') + ' - ' : '') + |
909 | 909 | environment.name + |
910 | - (@category ? "→ #{@category.full_name}" : '') | |
910 | + (@category ? " - #{@category.full_name}" : '') | |
911 | 911 | end |
912 | 912 | |
913 | 913 | def noosfero_javascript |
... | ... | @@ -921,6 +921,7 @@ module ApplicationHelper |
921 | 921 | 'lightbox', |
922 | 922 | 'colorpicker', |
923 | 923 | pngfix_stylesheet_path, |
924 | + 'jquery.ui/sunny/jquery-ui-1.8.2.custom', | |
924 | 925 | ] |
925 | 926 | end |
926 | 927 | |
... | ... | @@ -960,13 +961,16 @@ module ApplicationHelper |
960 | 961 | text_field_tag(name, value, options.merge(:class => 'colorpicker_field')) |
961 | 962 | end |
962 | 963 | |
963 | - # for now force currency to Brazillian format, like: "12.345,20" | |
964 | - def float_to_currency(price) | |
965 | - number_to_currency(price, :unit => 'R$', :separator => ',', :delimiter => '.') | |
966 | - end | |
967 | - | |
968 | 964 | def ui_icon(icon_type) |
969 | 965 | "<span class='ui-icon ui-icon-#{icon_type}' style='float:left; margin-right:7px;'></span>" |
970 | 966 | end |
971 | 967 | |
968 | + def ui_button(label, url, html_options = {}) | |
969 | + link_to(label, url, html_options.merge(:class => 'ui_button fg-button')) | |
970 | + end | |
971 | + | |
972 | + def ui_button_to_remote(label, options, html_options = {}) | |
973 | + link_to_remote(label, options, html_options.merge(:class => 'ui_button fg-button')) | |
974 | + end | |
975 | + | |
972 | 976 | end | ... | ... |
app/helpers/catalog_helper.rb
1 | 1 | module CatalogHelper |
2 | 2 | |
3 | 3 | include DisplayHelper |
4 | +include ManageProductsHelper | |
4 | 5 | |
5 | 6 | def display_products_list(profile, products) |
6 | 7 | data = '' |
... | ... | @@ -19,7 +20,7 @@ include DisplayHelper |
19 | 20 | content_tag('h1', _('Products/Services')) + content_tag('ul', data, :id => 'product_list') |
20 | 21 | end |
21 | 22 | |
22 | -private | |
23 | + private | |
23 | 24 | |
24 | 25 | def product_category_name(profile, product_category) |
25 | 26 | if profile.enabled? | ... | ... |
app/helpers/display_helper.rb
... | ... | @@ -2,7 +2,7 @@ module DisplayHelper |
2 | 2 | |
3 | 3 | def link_to_product(product, opts={}) |
4 | 4 | return _('No product') unless product |
5 | - target = product.enterprise.enabled? ? product.enterprise.public_profile_url.merge(:controller => 'catalog', :action => 'show', :id => product) : product.enterprise.url | |
5 | + target = product.enterprise.enabled? ? product.enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => product) : product.enterprise.url | |
6 | 6 | link_to content_tag( 'span', product.name ), |
7 | 7 | target, |
8 | 8 | opts | ... | ... |
app/helpers/manage_products_helper.rb
... | ... | @@ -49,12 +49,52 @@ module ManageProductsHelper |
49 | 49 | hierarchy.reverse.join(options[:separator] || ' → ') |
50 | 50 | end |
51 | 51 | |
52 | - def options_for_select_categories(categories) | |
52 | + def options_for_select_categories(categories, selected = nil) | |
53 | 53 | categories.sort_by{|cat| cat.name.transliterate}.map do |category| |
54 | - "<option value='#{category.id}'>#{category.name + (category.leaf? ? '': ' »')}</option>" | |
54 | + selected_attribute = selected.nil? ? '' : (category == selected ? "selected='selected'" : '') | |
55 | + "<option value='#{category.id}' #{selected_attribute}>#{category.name + (category.leaf? ? '': ' »')}</option>" | |
55 | 56 | end.join("\n") |
56 | 57 | end |
57 | 58 | |
59 | + def build_selects_for_ancestors(ancestors, last_level) | |
60 | + current_category = ancestors.shift | |
61 | + if current_category.nil? | |
62 | + content_tag('div', '<!-- no categories -->', | |
63 | + :class => 'categories_container', | |
64 | + :id => "categories_container_level#{ last_level }" | |
65 | + ) | |
66 | + else | |
67 | + content_tag('div', | |
68 | + select_tag('category_id', | |
69 | + options_for_select_categories(current_category.siblings + [current_category], current_category), | |
70 | + :size => 10, | |
71 | + :onchange => remote_function_to_update_categories_selection("categories_container_level#{ current_category.level + 1 }", :with => "'category_id=' + this.value") | |
72 | + ) + | |
73 | + build_selects_for_ancestors(ancestors, last_level), | |
74 | + :class => 'categories_container', | |
75 | + :id => "categories_container_level#{ current_category.level }" | |
76 | + ) | |
77 | + end | |
78 | + end | |
79 | + | |
80 | + def selects_for_all_ancestors(current_category) | |
81 | + build_selects_for_ancestors(current_category.ancestors.reverse + [current_category], current_category.level + 1) | |
82 | + end | |
83 | + | |
84 | + def select_for_new_category | |
85 | + content_tag('div', | |
86 | + render(:partial => 'categories_for_selection'), | |
87 | + :class => 'categories_container', | |
88 | + :id => 'categories_container_level0' | |
89 | + ) | |
90 | + end | |
91 | + | |
92 | + def categories_container(field_id_html, categories_selection_html, hierarchy_html = '') | |
93 | + field_id_html + | |
94 | + content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') + | |
95 | + content_tag('div', categories_selection_html, :id => 'categories_container_wrapper') | |
96 | + end | |
97 | + | |
58 | 98 | def select_for_categories(categories, level = 0) |
59 | 99 | if categories.empty? |
60 | 100 | content_tag('div', '', :id => 'no_subcategories') |
... | ... | @@ -68,4 +108,98 @@ module ManageProductsHelper |
68 | 108 | end |
69 | 109 | end |
70 | 110 | |
111 | + def edit_product_link(product, field, label, html_options = {}) | |
112 | + return '' unless (user && user.has_permission?('manage_products', profile)) | |
113 | + options = html_options.merge(:id => 'link-edit-product-' + field) | |
114 | + | |
115 | + link_to_remote(label, | |
116 | + {:update => "product-#{field}", | |
117 | + :url => { :controller => 'manage_products', :action => "edit", :id => product.id, :field => field }, | |
118 | + :method => :get}, | |
119 | + options) | |
120 | + end | |
121 | + | |
122 | + def edit_product_button(product, field, label, html_options = {}) | |
123 | + the_class = 'button with-text icon-edit' | |
124 | + if html_options.has_key?(:class) | |
125 | + the_class << ' ' << html_options[:class] | |
126 | + end | |
127 | + edit_product_link(product, field, label, html_options.merge(:class => the_class)) | |
128 | + end | |
129 | + | |
130 | + def edit_product_ui_button(product, field, label, html_options = {}) | |
131 | + return '' unless (user && user.has_permission?('manage_products', profile)) | |
132 | + options = html_options.merge(:id => 'edit-product-button-ui-' + field) | |
133 | + | |
134 | + ui_button_to_remote(label, | |
135 | + {:update => "product-#{field}", | |
136 | + :url => { :controller => 'manage_products', :action => "edit", :id => product.id, :field => field }, | |
137 | + :complete => "$('edit-product-button-ui-#{field}').hide()", | |
138 | + :method => :get}, | |
139 | + options) | |
140 | + end | |
141 | + | |
142 | + def cancel_edit_product_link(product, field, html_options = {}) | |
143 | + return '' unless (user && user.has_permission?('manage_products', profile)) | |
144 | + button_to_function(:cancel, _('Cancel'), nil, html_options) do |page| | |
145 | + page.replace_html "product-#{field}", :partial => "display_#{field}", :locals => {:product => product} | |
146 | + end | |
147 | + end | |
148 | + | |
149 | + def edit_product_category_link(product, html_options = {}) | |
150 | + return '' unless (user && user.has_permission?('manage_products', profile)) | |
151 | + options = html_options.merge(:id => 'link-edit-product-category') | |
152 | + link_to(_('Change category'), { :action => 'edit_category', :id => product.id}, options) | |
153 | + end | |
154 | + | |
155 | + def float_to_currency(value) | |
156 | + number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :format => "%u %n") | |
157 | + end | |
158 | + | |
159 | + def display_value(product) | |
160 | + price = product.price | |
161 | + unless price.blank? || price.zero? | |
162 | + unit = product.unit | |
163 | + return '' if unit.blank? | |
164 | + discount = product.discount | |
165 | + if discount.blank? || discount.zero? | |
166 | + display_price(_('Price: '), price, unit) | |
167 | + else | |
168 | + display_price_with_discount(price, unit, product.price_with_discount) | |
169 | + end | |
170 | + else | |
171 | + '' | |
172 | + end | |
173 | + end | |
174 | + | |
175 | + def display_price(label, price, unit) | |
176 | + content_tag('span', label, :class => 'field-name') + | |
177 | + content_tag('span', float_to_currency(price), :class => 'field-value') + | |
178 | + ' (%s)' % unit | |
179 | + end | |
180 | + | |
181 | + def display_price_with_discount(price, unit, price_with_discount) | |
182 | + original_value = content_tag('span', float_to_currency(price), :class => 'field-value') | |
183 | + discount_value = display_price(_('On sale: '), price_with_discount, unit) | |
184 | + content_tag('span', _('List price: '), :class => 'field-name') + original_value + "<p/>" + discount_value | |
185 | + end | |
186 | + | |
187 | + def display_qualifiers(product) | |
188 | + data = '' | |
189 | + product.product_qualifiers.each do |pq| | |
190 | + certified_by = pq.certifier ? _(' certified by %s') % link_to(pq.certifier.name, pq.certifier.link) : '' | |
191 | + data << content_tag('li', '✔ ' + pq.qualifier.name + certified_by, :class => 'product-qualifiers-item') | |
192 | + end | |
193 | + content_tag('ul', data, :id => 'product-qualifiers') | |
194 | + end | |
195 | + | |
196 | + def checkboxes_qualifiers(product, qualifier) | |
197 | + check_box_tag("product[qualifiers_list][#{qualifier.id}][qualifier_id]", qualifier.id, product.qualifiers.include?(qualifier)) + qualifier.name | |
198 | + end | |
199 | + | |
200 | + def select_certifiers(product, qualifier, certifiers) | |
201 | + relation = product.product_qualifiers.find(:first, :conditions => {:qualifier_id => qualifier.id}) | |
202 | + selected = relation.nil? ? 0 : relation.certifier_id | |
203 | + select_tag("product[qualifiers_list][#{qualifier.id}][certifier_id]", options_for_select([[_('Select...') , 0 ]] + certifiers.map {|c|[c.name, c.id]}, selected)) | |
204 | + end | |
71 | 205 | end | ... | ... |
app/models/environment.rb
... | ... | @@ -152,6 +152,9 @@ class Environment < ActiveRecord::Base |
152 | 152 | |
153 | 153 | has_many :roles |
154 | 154 | |
155 | + has_many :qualifiers | |
156 | + has_many :certifiers | |
157 | + | |
155 | 158 | acts_as_accessible |
156 | 159 | |
157 | 160 | def superior_intances |
... | ... | @@ -209,6 +212,10 @@ class Environment < ActiveRecord::Base |
209 | 212 | settings_items :help_message_to_add_enterprise, :type => String, :default => '' |
210 | 213 | settings_items :tip_message_enterprise_activation_question, :type => String, :default => '' |
211 | 214 | |
215 | + settings_items :currency_unit, :type => String, :default => '$' | |
216 | + settings_items :currency_separator, :type => String, :default => '.' | |
217 | + settings_items :currency_delimiter, :type => String, :default => ',' | |
218 | + | |
212 | 219 | def news_amount_by_folder=(amount) |
213 | 220 | settings[:news_amount_by_folder] = amount.to_i |
214 | 221 | end | ... | ... |
app/models/product.rb
... | ... | @@ -2,10 +2,14 @@ class Product < ActiveRecord::Base |
2 | 2 | belongs_to :enterprise |
3 | 3 | belongs_to :product_category |
4 | 4 | has_many :product_categorizations |
5 | + has_many :product_qualifiers | |
6 | + has_many :qualifiers, :through => :product_qualifiers | |
5 | 7 | |
6 | 8 | validates_uniqueness_of :name, :scope => :enterprise_id, :allow_nil => true |
7 | 9 | validates_presence_of :product_category |
10 | + | |
8 | 11 | validates_numericality_of :price, :allow_nil => true |
12 | + validates_numericality_of :discount, :allow_nil => true | |
9 | 13 | |
10 | 14 | after_update :save_image |
11 | 15 | |
... | ... | @@ -31,10 +35,36 @@ class Product < ActiveRecord::Base |
31 | 35 | |
32 | 36 | acts_as_searchable :fields => [ :name, :description, :category_full_name ] |
33 | 37 | |
34 | - xss_terminate :only => [ :name, :description ], :on => 'validation' | |
38 | + xss_terminate :only => [ :name ], :on => 'validation' | |
39 | + xss_terminate :only => [ :description ], :with => 'white_list', :on => 'validation' | |
35 | 40 | |
36 | 41 | acts_as_mappable |
37 | - | |
42 | + | |
43 | + def self.units | |
44 | + { | |
45 | + _('Litre') => 'litre', | |
46 | + _('Kilo') => 'kilo', | |
47 | + _('Meter') => 'meter', | |
48 | + _('Unit') => 'unit', | |
49 | + } | |
50 | + end | |
51 | + | |
52 | + def name | |
53 | + self[:name].blank? ? category_name : self[:name] | |
54 | + end | |
55 | + | |
56 | + def name=(value) | |
57 | + if (value == category_name) | |
58 | + self[:name] = nil | |
59 | + else | |
60 | + self[:name] = value | |
61 | + end | |
62 | + end | |
63 | + | |
64 | + def default_image(size='thumb') | |
65 | + '/images/icons-app/product-default-pic-%s.png' % size | |
66 | + end | |
67 | + | |
38 | 68 | def category_full_name |
39 | 69 | product_category ? product_category.full_name.split('/') : nil |
40 | 70 | end |
... | ... | @@ -60,13 +90,21 @@ class Product < ActiveRecord::Base |
60 | 90 | end |
61 | 91 | |
62 | 92 | def url |
63 | - enterprise.public_profile_url.merge(:controller => 'catalog', :action => 'show', :id => id) | |
93 | + enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => id) | |
64 | 94 | end |
65 | 95 | |
66 | 96 | def public? |
67 | 97 | enterprise.public_profile |
68 | 98 | end |
69 | 99 | |
100 | + def formatted_value(value) | |
101 | + ("%.2f" % self[value]).to_s.gsub('.', enterprise.environment.currency_separator) if self[value] | |
102 | + end | |
103 | + | |
104 | + def price_with_discount | |
105 | + price - discount if discount | |
106 | + end | |
107 | + | |
70 | 108 | def price=(value) |
71 | 109 | if value.is_a?(String) |
72 | 110 | super(currency_to_float(value)) |
... | ... | @@ -75,6 +113,14 @@ class Product < ActiveRecord::Base |
75 | 113 | end |
76 | 114 | end |
77 | 115 | |
116 | + def discount=(value) | |
117 | + if value.is_a?(String) | |
118 | + super(currency_to_float(value)) | |
119 | + else | |
120 | + super(value) | |
121 | + end | |
122 | + end | |
123 | + | |
78 | 124 | def currency_to_float( num ) |
79 | 125 | if num.count('.') == 1 && num.count(',') == 0 |
80 | 126 | # number like "12.34" |
... | ... | @@ -99,4 +145,17 @@ class Product < ActiveRecord::Base |
99 | 145 | return num.tr(',.','').to_f |
100 | 146 | end |
101 | 147 | |
148 | + def has_basic_info? | |
149 | + %w[description price].each do |field| | |
150 | + return true if !self.send(field).blank? | |
151 | + end | |
152 | + false | |
153 | + end | |
154 | + | |
155 | + def qualifiers_list=(qualifiers) | |
156 | + self.product_qualifiers.delete_all | |
157 | + qualifiers.each do |item| | |
158 | + self.product_qualifiers.create(item[1]) if item[1].has_key?('qualifier_id') | |
159 | + end | |
160 | + end | |
102 | 161 | end | ... | ... |
app/models/products_block.rb
... | ... | @@ -20,7 +20,7 @@ class ProductsBlock < Block |
20 | 20 | block_title(title) + |
21 | 21 | content_tag( |
22 | 22 | 'ul', |
23 | - products.map {|product| content_tag('li', link_to(product.name, product.url, :style => 'background-image:url(%s)' % ( product.image ? product.image.public_filename(:minor) : '/images/icons-app/product-default-pic-minor.png' )), :class => 'product' )} | |
23 | + products.map {|product| content_tag('li', link_to(product.name, product.url, :style => 'background-image:url(%s)' % ( product.image ? product.image.public_filename(:minor) : product.default_image('minor'))), :class => 'product' )} | |
24 | 24 | ) |
25 | 25 | end |
26 | 26 | ... | ... |
app/models/profile.rb
... | ... | @@ -386,7 +386,7 @@ class Profile < ActiveRecord::Base |
386 | 386 | |
387 | 387 | def url_options |
388 | 388 | options = { :host => default_hostname, :profile => (own_hostname ? nil : self.identifier) } |
389 | - Noosfero.url_options.merge(options) | |
389 | + options.merge(Noosfero.url_options.merge(options)) | |
390 | 390 | end |
391 | 391 | |
392 | 392 | private :generate_url, :url_options | ... | ... |
app/views/catalog/show.rhtml
... | ... | @@ -1,25 +0,0 @@ |
1 | -<div id="show_product"> | |
2 | - | |
3 | -<h1> <%= @product.name %> </h1> | |
4 | - | |
5 | -<%= image_tag @product.image.public_filename, :class => 'product-pic' if @product.image %> | |
6 | - | |
7 | -<div class="product_description"> | |
8 | -<%= txt2html @product.description if @product.description %> | |
9 | -</div> | |
10 | - | |
11 | -<% if @product.price %> | |
12 | - <p class="product_price"> | |
13 | - <%= _('Price: %s') % ( "<strong>%.2f</strong>" % @product.price) %> | |
14 | - </p> | |
15 | -<% end %> | |
16 | - | |
17 | -<p class="product_category"> | |
18 | -<%= _('Category: %s ') % link_to_product_category(@product.product_category) %> | |
19 | -</p> | |
20 | - | |
21 | -<% button_bar do %> | |
22 | - <%= button :back, _("%s's products/services listing") % profile.name, :action => 'index', :id => nil %> | |
23 | -<% end %> | |
24 | - | |
25 | -</div> |
app/views/cms/_upload_file_form.rhtml
app/views/layouts/_javascript.rhtml
1 | -<%= javascript_include_tag :defaults, 'jquery-latest.js', 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'colorpicker', 'colorpicker-noosfero', 'reflection', :cache => 'cache-general' %> | |
1 | +<%= javascript_include_tag :defaults, 'jquery-latest.js', 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'colorpicker', 'colorpicker-noosfero', 'reflection', :cache => 'cache-general' %> | ... | ... |
app/views/layouts/application.rhtml
... | ... | @@ -15,7 +15,6 @@ |
15 | 15 | <%= |
16 | 16 | # Load the principal css files: |
17 | 17 | stylesheet_link_tag(noosfero_stylesheets, :cache => 'cache') + |
18 | - stylesheet_link_tag('jquery.ui/smoothness/jquery-ui-1.8.2.custom') + | |
19 | 18 | stylesheet_import( %w( common help menu article button search blocks forms login-box ), |
20 | 19 | :themed_source => true ) + "\n" + |
21 | 20 | import_blocks_stylesheets(:themed_source => true) + "\n" + |
... | ... | @@ -126,5 +125,10 @@ |
126 | 125 | app/views/shared/noosfero_layout_features.rhtml! %> |
127 | 126 | <%= noosfero_layout_features %> |
128 | 127 | |
128 | + <script type='text/javascript'> | |
129 | + // transform all element with class ui_button in a jQuery UI button | |
130 | + render_jquery_ui_buttons() | |
131 | + </script> | |
132 | + | |
129 | 133 | </body> |
130 | 134 | </html> | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +<%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> | |
2 | +<div id='display-product-info'> | |
3 | + <%= display_value(@product) %> | |
4 | + <%= display_qualifiers(@product) %> | |
5 | +</div> | |
6 | + | |
7 | +<div id='display-product-description'><%= @product.description %></div> | |
8 | + | |
9 | +<% if @product.has_basic_info? %> | |
10 | + <%= edit_product_button(@product, 'info', _('Edit basic information')) %> | |
11 | +<% else %> | |
12 | + <%= edit_product_ui_button(@product, 'info', _('Add description, price and other basic information'), :title => _('Click here to add description, price, discount and qualifiers/certifiers to make your product more attractive and detailed for the consumers'), 'data-primary-icon' => 'ui-icon-pencil', 'data-secondary-icon' => 'ui-icon-triangle-1-s') %> | |
13 | + <%= javascript_tag("render_jquery_ui_buttons('edit-product-button-ui-info')") %> | |
14 | +<% end%> | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +<div id='display-product-image'> | |
2 | + <%= image_tag (@product.reload.image ? @product.image.public_filename : @product.default_image('thumb')), :class => 'product-pic' %> | |
3 | +</div> | |
4 | + | |
5 | +<% form_for(:product, :url => { :controller => 'manage_products', :action => 'edit', :id => @product, :field => 'image' }, :html => { :method => 'post', :id => 'uploadForm', :multipart => true}) do |f| %> | |
6 | + <% f.fields_for :image_builder, @product.image do |i| %> | |
7 | + <%= i.file_field( :uploaded_data, { :size => 10 } ) %> | |
8 | + <p><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %></p> | |
9 | + <% end %> | |
10 | + | |
11 | + <%= submit_button 'save', _('Save') %> | |
12 | + <%= cancel_edit_product_link(@product, 'image') %> | |
13 | +<% end %> | |
14 | + | |
15 | +<script type="text/javascript"> | |
16 | + jQuery("#uploadForm").ajaxForm({ | |
17 | + beforeSubmit: function(a,f,o) { | |
18 | + o.loading = open_loading('<%= _('loading... ') %>'); | |
19 | + o.loaded = close_loading(); | |
20 | + }, | |
21 | + target: '#product-image' | |
22 | + }); | |
23 | +</script> | |
24 | + | |
25 | +<% if errors %> | |
26 | + <%= render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } %> | |
27 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,49 @@ |
1 | +<% if errors %> | |
2 | + <%= render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } %> | |
3 | +<% end %> | |
4 | + | |
5 | +<%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> | |
6 | +<% remote_form_for(@product, | |
7 | + :loading => "open_loading('#{ _('loading...') }')", | |
8 | + :loaded => 'close_loading()', | |
9 | + :before => ("tinyMCE.triggerSave()" unless Rails.env == 'test'), | |
10 | + :update => 'product-info', | |
11 | + :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'info'}, | |
12 | + :html => {:id => 'product-info-form', :method => 'post'}) do |f| %> | |
13 | + <%= labelled_form_field(_('Description:'), f.text_area(:description, :rows => 15, :style => 'width: 90%;')) %> | |
14 | + <%= labelled_form_field(_('Price (%s):') % environment.currency_unit, f.text_field(:price, :value => @product.formatted_value(:price), :onKeyPress => "return numbersonly(event, '#{environment.currency_separator}');")) %> | |
15 | + <%= labelled_form_field(_('Unit:'), f.select(:unit, Product.units)) %> | |
16 | + <%= labelled_form_field(_('Discount (%s):') % environment.currency_unit, f.text_field(:discount, :value => @product.formatted_value(:discount), :onKeyPress => "return numbersonly(event, '#{environment.currency_separator}');")) %> | |
17 | + <div class='formlabel'><%= _('Available:') %></div> | |
18 | + <div class='formfield'> | |
19 | + <%= labelled_radio_button( _('Yes'), 'product[available]', 'true', @product.available) %> | |
20 | + <%= labelled_radio_button( _('No'), 'product[available]', 'false', !@product.available) %> | |
21 | + </div> | |
22 | + | |
23 | + | |
24 | + <% if !environment.qualifiers.empty? %> | |
25 | + <table id='product-qualifiers-list'> | |
26 | + <tr> | |
27 | + <th><%= _('Qualifier') %></th> | |
28 | + <th><%= _('Certifier') %></th> | |
29 | + </tr> | |
30 | + <% environment.qualifiers.each do |qualifier| %> | |
31 | + <tr> | |
32 | + <td> | |
33 | + <%= checkboxes_qualifiers(@product, qualifier) %> | |
34 | + </td> | |
35 | + <td> | |
36 | + <%= select_certifiers(@product, qualifier, environment.certifiers) %> | |
37 | + </td> | |
38 | + </tr> | |
39 | + <% end %> | |
40 | + </table> | |
41 | + <% end %> | |
42 | + | |
43 | + <% button_bar do %> | |
44 | + <%= submit_button :save, _('Save') %> | |
45 | + <%= cancel_edit_product_link(@product, 'info') %> | |
46 | + <% end %> | |
47 | +<% end %> | |
48 | + | |
49 | +<br style='clear:both'> | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +<% remote_form_for(@product, | |
2 | + :loading => "open_loading('#{ _('loading...') }')", | |
3 | + :loaded => 'close_loading()', | |
4 | + :update => 'product-name', | |
5 | + :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'name'}, | |
6 | + :html => {:method => 'post'}) do |f| %> | |
7 | + <%= f.text_field(:name, :value => @product.name, :class => 'name_edition') %> | |
8 | + | |
9 | + <% button_bar do %> | |
10 | + <%= submit_button :save, _('Save') %> | |
11 | + <%= cancel_edit_product_link(@product, 'name') %> | |
12 | + <% end %> | |
13 | +<% end %> | |
14 | + | |
15 | +<script type="text/javascript"> | |
16 | + jQuery('#product_name').focus().select(); | |
17 | +</script> | |
18 | + | |
19 | +<% if errors %> | |
20 | + <%= render :partial => 'shared/dialog_error_messages', :locals => { :object_name => 'product' } %> | |
21 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,34 @@ |
1 | +<div class=product-category-hierarchy> | |
2 | + <%= hierarchy_category_navigation(@product.product_category, :make_links => false)%> | |
3 | +</div> | |
4 | + | |
5 | +<div id="category-product-edition"> | |
6 | + | |
7 | + <h2><%= @product.name %></h2> | |
8 | + | |
9 | + <div id='request_result_message' style='display: none'></div> | |
10 | + | |
11 | + <% remote_form_for(:product, @product, | |
12 | + :loading => "open_loading('#{ _('loading...') }')", | |
13 | + :loaded => "close_loading()", | |
14 | + :update => "request_result_message", | |
15 | + :url => {:action => 'edit_category', :id => @product, :field => 'category'}, | |
16 | + :html => {:method => 'post', :id => 'product_category_form'}) do |f| %> | |
17 | + | |
18 | + <h3><%= _('Edit category of this product:') %></h3> | |
19 | + | |
20 | + <%= categories_container(f.hidden_field('product_category_id'), selects_for_all_ancestors(@category), hierarchy_category_navigation(@category, :make_links => true)) %> | |
21 | + | |
22 | + <div id='categories_selection_actionbar'> | |
23 | + <%= button(:back, _('Back to product'), :action => 'show', :id => @product) %> | |
24 | + <span id='save_and_continue_wrapper'> | |
25 | + <%= submit_button(:save, _('Save and continue'), :id => 'save_and_continue') %> | |
26 | + <span class='tooltip' id='save_and_continue_disabled_tooltip'> | |
27 | + <%= ui_icon(:alert) %> | |
28 | + <%= _('This category does not allow registration of products, select a more specific category') %> | |
29 | + </span> | |
30 | + </span> | |
31 | + </div> | |
32 | + | |
33 | + <% end %> | |
34 | +</div> | ... | ... |
app/views/manage_products/index.rhtml
... | ... | @@ -16,7 +16,6 @@ |
16 | 16 | <td><strong><%= link_to product.name, :action => 'show', :id => product %></strong></td> |
17 | 17 | <td><%= product.price %></td> |
18 | 18 | <td> |
19 | - <%= button :edit, _('Edit'), :action => 'edit', :id => product %> | |
20 | 19 | <%= button :delete, _('Destroy'), :action => 'destroy', :id => product %> |
21 | 20 | </td> |
22 | 21 | </tr> | ... | ... |
app/views/manage_products/new.rhtml
... | ... | @@ -6,19 +6,11 @@ |
6 | 6 | :loading => "open_loading('#{ _('loading...') }')", |
7 | 7 | :update => "request_result_message", |
8 | 8 | :url => {:action => 'new'}, |
9 | - :html => {:method => 'post', :id => 'new_product_form'} do |f| %> | |
9 | + :html => {:method => 'post', :id => 'product_category_form'} do |f| %> | |
10 | 10 | |
11 | 11 | <h3><%= _('Select the category of the new product or service') %></h3> |
12 | 12 | |
13 | - <%= f.hidden_field 'product_category_id' %> | |
14 | - | |
15 | - <div id='hierarchy_navigation'> </div> | |
16 | - | |
17 | - <div id='categories_container_wrapper'> | |
18 | - <div class='categories_container' id='categories_container_level0'> | |
19 | - <%= render :partial => 'categories_for_selection' %> | |
20 | - </div> | |
21 | - </div> | |
13 | + <%= categories_container(f.hidden_field('product_category_id'), select_for_new_category) %> | |
22 | 14 | |
23 | 15 | <div id='categories_selection_actionbar'> |
24 | 16 | <%= button :back, _('Back to the product listing'), :action => 'index' %> | ... | ... |
app/views/manage_products/show.rhtml
1 | -<h3> <%= @product.name %> </h3> | |
1 | +<div id="product-category"> | |
2 | + <%= render :partial => 'manage_products/display_category', :locals => {:product => @product} %> | |
3 | +</div> | |
2 | 4 | |
3 | -<p> <%= image_tag @product.image.public_filename if @product.image %> </p> | |
4 | -<p> <strong><%= _('Price:') %></strong> <%= @product.price %> </p> | |
5 | -<p> <strong><%= _('Description:') %></strong> <%= txt2html @product.description if @product.description %> </p> | |
6 | -<p> <strong><%= _('Category:') %></strong> <%= link_to_product_category(@product.product_category) %> </p> | |
5 | +<div id="show_product"> | |
7 | 6 | |
8 | -<%= button :back, _('Back'), :action => 'index' %> | |
9 | - | |
10 | -<%= button :delete, _('Destroy'), :action => 'destroy', :id => @product %> | |
11 | -<%= button :edit, _('Edit'), :action => 'edit', :id => @product %> | |
7 | + <div id='product-name'> | |
8 | + <%= render :partial => 'manage_products/display_name', :locals => {:product => @product} %> | |
9 | + </div> | |
12 | 10 | |
11 | + <div id='product-details'> | |
12 | + <div id='product-image'> | |
13 | + <%= render :partial => 'manage_products/display_image', :locals => {:product => @product} %> | |
14 | + </div> | |
15 | + | |
16 | + <div id='product-info'> | |
17 | + <%= render :partial => 'manage_products/display_info', :locals => {:product => @product} %> | |
18 | + </div> | |
19 | + | |
20 | + </div> | |
21 | +</div> | |
22 | + | |
23 | +<% button_bar do %> | |
24 | + <%= button :back, _('Back to the product listing'), :action => 'index' %> | |
25 | + <%= button :delete, _('Remove product or service'), {:action => 'destroy', :id => @product}, :class => 'requires-permission-manage_products', :style => 'display:none;' %> | |
26 | +<% end %> | ... | ... |
app/views/shared/_dialog_error_messages.rhtml
app/views/shared/tiny_mce.rhtml
1 | 1 | <%= javascript_include_tag 'tinymce/jscripts/tiny_mce/tiny_mce.js' %> |
2 | 2 | <script type="text/javascript"> |
3 | 3 | var myplugins = "searchreplace,print,table"; |
4 | + var first_line, second_line; | |
5 | + var mode = '<%= mode ||= false %>' | |
6 | + <% if mode %> | |
7 | + first_line = "fontsizeselect,bold,italic,underline,bullist,numlist,justifyleft,justifycenter,justifyright,link,unlink" | |
8 | + second_line = "" | |
9 | + <% else %> | |
10 | + first_line = "print,separator,copy,paste,separator,undo,redo,separator,search,replace,separator,fontsizeselect,formatselect" | |
11 | + second_line = "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,link,unlink,image,table,separator,cleanup,code" | |
12 | + <% end %> | |
13 | + | |
4 | 14 | if (tinymce.isIE) { |
5 | 15 | // the paste plugin is only useful in Internet Explorer |
6 | 16 | myplugins = "paste," + myplugins; |
... | ... | @@ -14,8 +24,8 @@ tinyMCE.init({ |
14 | 24 | plugins: myplugins, |
15 | 25 | theme_advanced_toolbar_location : "top", |
16 | 26 | theme_advanced_layout_manager: 'SimpleLayout', |
17 | - theme_advanced_buttons1 : "print,separator,copy,paste,separator,undo,redo,separator,search,replace,separator,fontsizeselect,formatselect", | |
18 | - theme_advanced_buttons2 : "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,link,unlink,image,table,separator,cleanup,code", | |
27 | + theme_advanced_buttons1 : first_line, | |
28 | + theme_advanced_buttons2 : second_line, | |
19 | 29 | theme_advanced_buttons3 : "", |
20 | 30 | theme_advanced_blockformats :"p,address,pre,h2,h3,h4,h5,h6", |
21 | 31 | paste_auto_cleanup_on_paste : true, | ... | ... |
config/routes.rb
... | ... | @@ -60,7 +60,6 @@ ActionController::Routing::Routes.draw do |map| |
60 | 60 | |
61 | 61 | # catalog |
62 | 62 | map.catalog 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format}/ |
63 | - map.product 'catalog/:profile/:id', :controller => 'catalog', :action => 'show', :profile => /#{Noosfero.identifier_format}/ | |
64 | 63 | |
65 | 64 | # invite |
66 | 65 | map.invite 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format}/ | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +class AddColumnsToProducts < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_column :products, :unit, :string | |
4 | + add_column :products, :discount, :float | |
5 | + add_column :products, :available, :boolean | |
6 | + end | |
7 | + | |
8 | + def self.down | |
9 | + remove_column :products, :unit | |
10 | + remove_column :products, :discount | |
11 | + remove_column :products, :available | |
12 | + end | |
13 | +end | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +class CreateProductQualifiers < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + create_table :product_qualifiers do |t| | |
4 | + t.references :product | |
5 | + t.references :qualifier | |
6 | + t.references :certifier | |
7 | + t.timestamps | |
8 | + end | |
9 | + end | |
10 | + | |
11 | + def self.down | |
12 | + drop_table :product_qualifiers | |
13 | + end | |
14 | +end | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +class CreateCertifiers < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + create_table :certifiers do |t| | |
4 | + t.string :name | |
5 | + t.string :description | |
6 | + t.string :link | |
7 | + t.references :environment | |
8 | + | |
9 | + t.timestamps | |
10 | + end | |
11 | + end | |
12 | + | |
13 | + def self.down | |
14 | + drop_table :certifiers | |
15 | + end | |
16 | +end | ... | ... |
db/schema.rb
... | ... | @@ -141,6 +141,15 @@ ActiveRecord::Schema.define(:version => 20100621235235) do |
141 | 141 | add_index "categories_profiles", ["category_id"], :name => "index_categories_profiles_on_category_id" |
142 | 142 | add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id" |
143 | 143 | |
144 | + create_table "certifiers", :force => true do |t| | |
145 | + t.string "name" | |
146 | + t.string "description" | |
147 | + t.string "link" | |
148 | + t.integer "environment_id" | |
149 | + t.datetime "created_at" | |
150 | + t.datetime "updated_at" | |
151 | + end | |
152 | + | |
144 | 153 | create_table "comments", :force => true do |t| |
145 | 154 | t.string "title" |
146 | 155 | t.text "body" |
... | ... | @@ -230,6 +239,14 @@ ActiveRecord::Schema.define(:version => 20100621235235) do |
230 | 239 | add_index "product_categorizations", ["category_id"], :name => "index_product_categorizations_on_category_id" |
231 | 240 | add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id" |
232 | 241 | |
242 | + create_table "product_qualifiers", :force => true do |t| | |
243 | + t.integer "product_id" | |
244 | + t.integer "qualifier_id" | |
245 | + t.integer "certifier_id" | |
246 | + t.datetime "created_at" | |
247 | + t.datetime "updated_at" | |
248 | + end | |
249 | + | |
233 | 250 | create_table "products", :force => true do |t| |
234 | 251 | t.integer "enterprise_id" |
235 | 252 | t.integer "product_category_id" |
... | ... | @@ -241,6 +258,9 @@ ActiveRecord::Schema.define(:version => 20100621235235) do |
241 | 258 | t.datetime "updated_at" |
242 | 259 | t.float "lat" |
243 | 260 | t.float "lng" |
261 | + t.string "unit" | |
262 | + t.float "discount" | |
263 | + t.boolean "available" | |
244 | 264 | t.boolean "highlighted" |
245 | 265 | end |
246 | 266 | |
... | ... | @@ -276,6 +296,13 @@ ActiveRecord::Schema.define(:version => 20100621235235) do |
276 | 296 | |
277 | 297 | add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" |
278 | 298 | |
299 | + create_table "qualifiers", :force => true do |t| | |
300 | + t.string "name" | |
301 | + t.integer "environment_id" | |
302 | + t.datetime "created_at" | |
303 | + t.datetime "updated_at" | |
304 | + end | |
305 | + | |
279 | 306 | create_table "refused_join_community", :id => false, :force => true do |t| |
280 | 307 | t.integer "person_id" |
281 | 308 | t.integer "community_id" | ... | ... |
features/manage_products.feature
... | ... | @@ -10,18 +10,28 @@ Feature: manage products |
10 | 10 | | identifier | owner | name | enabled | |
11 | 11 | | redemoinho | joaosilva | Rede Moinho | true | |
12 | 12 | And feature "disable_products_for_enterprises" is disabled on environment |
13 | - And I am logged in as "joaosilva" | |
14 | - And I am on Rede Moinho's control panel | |
15 | - And I follow "Manage Products and Services" | |
16 | 13 | |
17 | 14 | Scenario: listing products and services |
15 | + Given I am logged in as "joaosilva" | |
16 | + And I am on Rede Moinho's control panel | |
17 | + And I follow "Manage Products and Services" | |
18 | 18 | Then I should see "Listing products and services" |
19 | 19 | |
20 | + Scenario: see button to back in categories hierarchy | |
21 | + Given I am logged in as "joaosilva" | |
22 | + And I am on Rede Moinho's control panel | |
23 | + And I follow "Manage Products and Services" | |
24 | + When I follow "New product or service" | |
25 | + Then I should see "Back to the product listing" link | |
26 | + | |
20 | 27 | Scenario: see toplevel categories |
21 | 28 | Given the following product_categories |
22 | 29 | | name | |
23 | 30 | | Products | |
24 | 31 | | Services | |
32 | + Given I am logged in as "joaosilva" | |
33 | + And I am on Rede Moinho's control panel | |
34 | + And I follow "Manage Products and Services" | |
25 | 35 | When I follow "New product or service" |
26 | 36 | Then I should see "Products" |
27 | 37 | And I should see "Service" |
... | ... | @@ -35,6 +45,9 @@ Feature: manage products |
35 | 45 | | name | parent | |
36 | 46 | | Computers level1 | products-level0 | |
37 | 47 | | DVDs level1 | products-level0 | |
48 | + Given I am logged in as "joaosilva" | |
49 | + And I am on Rede Moinho's control panel | |
50 | + And I follow "Manage Products and Services" | |
38 | 51 | When I follow "New product or service" |
39 | 52 | And I select "Products level0 »" |
40 | 53 | Then I should see "Computers level1" |
... | ... | @@ -50,6 +63,9 @@ Feature: manage products |
50 | 63 | | name | parent | |
51 | 64 | | Computers level1 | products-level0 | |
52 | 65 | | Software development level1 | services-level0 | |
66 | + Given I am logged in as "joaosilva" | |
67 | + And I am on Rede Moinho's control panel | |
68 | + And I follow "Manage Products and Services" | |
53 | 69 | When I follow "New product or service" |
54 | 70 | And I select "Products level0 »" |
55 | 71 | And I select "Computers level1" |
... | ... | @@ -65,6 +81,9 @@ Feature: manage products |
65 | 81 | And the following product_category |
66 | 82 | | name | parent | |
67 | 83 | | Computers | products | |
84 | + Given I am logged in as "joaosilva" | |
85 | + And I am on Rede Moinho's control panel | |
86 | + And I follow "Manage Products and Services" | |
68 | 87 | When I follow "New product or service" |
69 | 88 | And I select "Products »" |
70 | 89 | And I select "Computers" |
... | ... | @@ -78,6 +97,9 @@ Feature: manage products |
78 | 97 | Given the following product_category |
79 | 98 | | name | parent | |
80 | 99 | | Category Level 1 | toplevel-product-categories | |
100 | + Given I am logged in as "joaosilva" | |
101 | + And I am on Rede Moinho's control panel | |
102 | + And I follow "Manage Products and Services" | |
81 | 103 | When I follow "New product or service" |
82 | 104 | And I select "Toplevel Product Categories »" |
83 | 105 | And I select "Category Level 1" |
... | ... | @@ -89,6 +111,7 @@ Feature: manage products |
89 | 111 | Given the following product_category |
90 | 112 | | name | |
91 | 113 | | Only for test | |
114 | + And I am logged in as "joaosilva" | |
92 | 115 | When I go to /myprofile/redemoinho/manage_products/new |
93 | 116 | Then the "#save_and_continue" button should not be enabled |
94 | 117 | |
... | ... | @@ -97,6 +120,9 @@ Feature: manage products |
97 | 120 | Given the following product_category |
98 | 121 | | name | |
99 | 122 | | Browsers (accept categories) | |
123 | + Given I am logged in as "joaosilva" | |
124 | + And I am on Rede Moinho's control panel | |
125 | + And I follow "Manage Products and Services" | |
100 | 126 | When I follow "New product or service" |
101 | 127 | And I select "Browsers (accept categories)" |
102 | 128 | Then the "Save and continue" button should be enabled |
... | ... | @@ -106,6 +132,9 @@ Feature: manage products |
106 | 132 | Given the following product_category |
107 | 133 | | name | accept_products | |
108 | 134 | | Browsers | false | |
135 | + Given I am logged in as "joaosilva" | |
136 | + And I am on Rede Moinho's control panel | |
137 | + And I follow "Manage Products and Services" | |
109 | 138 | When I follow "New product or service" |
110 | 139 | And I select "Browsers" |
111 | 140 | Then the "#save_and_continue" button should not be enabled |
... | ... | @@ -115,16 +144,23 @@ Feature: manage products |
115 | 144 | Given the following product_category |
116 | 145 | | name | |
117 | 146 | | Bicycle | |
147 | + Given I am logged in as "joaosilva" | |
148 | + And I am on Rede Moinho's control panel | |
149 | + And I follow "Manage Products and Services" | |
118 | 150 | When I follow "New product or service" |
119 | 151 | And I select "Bicycle" |
120 | 152 | And I press "Save and continue" |
121 | - Then I should see "Category: Bicycle" | |
153 | + Then I should see "Bicycle" | |
154 | + And I should see "Change category" | |
122 | 155 | |
123 | 156 | @selenium |
124 | 157 | Scenario: stay on the same place after error on save |
125 | 158 | Given the following product_category |
126 | 159 | | name | |
127 | 160 | | Bicycle | |
161 | + Given I am logged in as "joaosilva" | |
162 | + And I am on Rede Moinho's control panel | |
163 | + And I follow "Manage Products and Services" | |
128 | 164 | And I follow "New product or service" |
129 | 165 | And I select "Bicycle" |
130 | 166 | And I press "Save and continue" |
... | ... | @@ -134,3 +170,184 @@ Feature: manage products |
134 | 170 | And I press "Save and continue" |
135 | 171 | Then I should be on Rede Moinho's new product page |
136 | 172 | And I should see "Bicycle" |
173 | + | |
174 | + Scenario: a user with permission can see edit links | |
175 | + Given the following product_category | |
176 | + | name | | |
177 | + | Bicycle | | |
178 | + And the following products | |
179 | + | owner | category | name | description | | |
180 | + | redemoinho | bicycle | Bike | Red bicycle | | |
181 | + And I am logged in as "joaosilva" | |
182 | + When I go to Rede Moinho's page of product Bike | |
183 | + Then I should see "Change category" | |
184 | + And I should see "Edit name" | |
185 | + And I should see "Edit basic information" | |
186 | + And I should see "Change image" | |
187 | + | |
188 | + Scenario: an allowed user will see a different button when has no basic info | |
189 | + Given the following product_category | |
190 | + | name | | |
191 | + | Bicycle | | |
192 | + And the following products | |
193 | + | owner | category | name | | |
194 | + | redemoinho | bicycle | Bike | | |
195 | + And I am logged in as "joaosilva" | |
196 | + When I go to Rede Moinho's page of product Bike | |
197 | + Then I should see "Change category" | |
198 | + And I should see "Edit name" | |
199 | + And I should see "Add description, price and other basic information" | |
200 | + And I should see "Change image" | |
201 | + | |
202 | + Scenario: a not logged user cannot see edit links | |
203 | + Given I am not logged in | |
204 | + And the following product_category | |
205 | + | name | | |
206 | + | Bicycle | | |
207 | + And the following products | |
208 | + | owner | category | name | description | | |
209 | + | redemoinho | bicycle | Bike | Red bicycle | | |
210 | + When I go to Rede Moinho's page of product Bike | |
211 | + Then I should not see "Change category" | |
212 | + And I should not see "Edit name" | |
213 | + And I should not see "Edit basic information" | |
214 | + And I should not see "Change image" | |
215 | + | |
216 | + Scenario: a not allowed user cannot see edit links | |
217 | + Given the following users | |
218 | + | login | name | | |
219 | + | mariasantos | Maria Santos | | |
220 | + And the following product_category | |
221 | + | name | | |
222 | + | Bicycle | | |
223 | + And the following products | |
224 | + | owner | category | name | description | | |
225 | + | redemoinho | bicycle | Bike | Red bicycle | | |
226 | + And I am logged in as "mariasantos" | |
227 | + When I go to Rede Moinho's page of product Bike | |
228 | + Then I should not see "Change category" | |
229 | + And I should not see "Edit name" | |
230 | + And I should not see "Edit basic information" | |
231 | + And I should not see "Change image" | |
232 | + | |
233 | + @selenium | |
234 | + Scenario: edit name of a product | |
235 | + Given the following product_category | |
236 | + | name | | |
237 | + | Bicycle | | |
238 | + And the following products | |
239 | + | owner | category | name | | |
240 | + | redemoinho | bicycle | Bike | | |
241 | + And I am logged in as "joaosilva" | |
242 | + When I go to Rede Moinho's page of product Bike | |
243 | + And I follow "Edit name" | |
244 | + And I fill in "product_name" with "Red bicycle" | |
245 | + And I press "Save" | |
246 | + Then I should see "Red bicycle" | |
247 | + And I should be on Rede Moinho's page of product Red bicycle | |
248 | + | |
249 | + @selenium | |
250 | + Scenario: cancel edition of a product name | |
251 | + Given the following product_category | |
252 | + | name | | |
253 | + | Bicycle | | |
254 | + And the following products | |
255 | + | owner | category | name | | |
256 | + | redemoinho | bicycle | Bike | | |
257 | + And I am logged in as "joaosilva" | |
258 | + When I go to Rede Moinho's page of product Bike | |
259 | + And I follow "Edit name" | |
260 | + When I follow "Cancel" | |
261 | + Then I should see "Bike" | |
262 | + | |
263 | + @selenium | |
264 | + Scenario: edit category of a product | |
265 | + Given the following product_category | |
266 | + | name | | |
267 | + | Eletronics | | |
268 | + And the following product_categories | |
269 | + | name | parent | | |
270 | + | Computers | eletronics | | |
271 | + | DVDs | eletronics | | |
272 | + And the following products | |
273 | + | owner | category | name | | |
274 | + | redemoinho | computers | Generic pc | | |
275 | + And I am logged in as "joaosilva" | |
276 | + When I go to Rede Moinho's page of product Generic pc | |
277 | + And I follow "Change category" | |
278 | + And I select "Eletronics »" | |
279 | + Then I select "DVDs" | |
280 | + And I press "Save and continue" | |
281 | + Then I should see "Eletronics → DVDs" | |
282 | + | |
283 | + @selenium | |
284 | + Scenario: cancel edition of a product category | |
285 | + Given the following product_category | |
286 | + | name | | |
287 | + | Eletronics | | |
288 | + And the following product_categories | |
289 | + | name | parent | | |
290 | + | Computers | eletronics | | |
291 | + | DVDs | eletronics | | |
292 | + And the following products | |
293 | + | owner | category | name | | |
294 | + | redemoinho | computers | Generic pc | | |
295 | + And I am logged in as "joaosilva" | |
296 | + When I go to Rede Moinho's page of product Generic pc | |
297 | + And I follow "Change category" | |
298 | + When I follow "Back to product" | |
299 | + Then I should see "Eletronics → Computers" | |
300 | + | |
301 | + | |
302 | + @selenium | |
303 | + Scenario: edit image of a product | |
304 | + Given the following product_category | |
305 | + | name | | |
306 | + | Eletronics | | |
307 | + And the following product_categories | |
308 | + | name | parent | | |
309 | + | Computers | eletronics | | |
310 | + | DVDs | eletronics | | |
311 | + And the following products | |
312 | + | owner | category | name | | |
313 | + | redemoinho | computers | Generic pc | | |
314 | + And I am logged in as "joaosilva" | |
315 | + When I go to Rede Moinho's page of product Generic pc | |
316 | + And I follow "Change image" | |
317 | + When I follow "Cancel" | |
318 | + Then I should be on Rede Moinho's page of product Generic pc | |
319 | + | |
320 | + # FIXME Not working because of tinyMCE plus selenium | |
321 | + # @selenium | |
322 | + # Scenario: edit description of a product | |
323 | + # Given the following product_category | |
324 | + # | name | | |
325 | + # | Bicycle | | |
326 | + # And the following products | |
327 | + # | owner | category | name | description | | |
328 | + # | redemoinho | bicycle | Bike | A new red bicycle | | |
329 | + # And I am logged in as "joaosilva" | |
330 | + # When I go to Rede Moinho's page of product Bike | |
331 | + # Then I should see "A new red bicycle" | |
332 | + # And I follow "Edit basic information" | |
333 | + # And I type in tinyMCE field "Description" the text "An used red bicycle" | |
334 | + # And I press "Save" | |
335 | + # Then I should not see "A new red bicycle" | |
336 | + # And I should see "An used red bicycle" | |
337 | + # And I should be on Rede Moinho's page of product Bike | |
338 | + | |
339 | + @selenium | |
340 | + Scenario: cancel edition of a product description | |
341 | + Given the following product_category | |
342 | + | name | | |
343 | + | Bicycle | | |
344 | + And the following products | |
345 | + | owner | category | name | description | | |
346 | + | redemoinho | bicycle | Bike | A new red bicycle | | |
347 | + And I am logged in as "joaosilva" | |
348 | + When I go to Rede Moinho's page of product Bike | |
349 | + Then I should see "A new red bicycle" | |
350 | + And I follow "Edit basic information" | |
351 | + When I follow "Cancel" | |
352 | + Then I should see "A new red bicycle" | |
353 | + And I should be on Rede Moinho's page of product Bike | ... | ... |
features/step_definitions/noosfero_steps.rb
features/support/paths.rb
... | ... | @@ -54,6 +54,14 @@ module NavigationHelpers |
54 | 54 | when /^(.+)'s new product page/ |
55 | 55 | '/myprofile/%s/manage_products/new' % Profile.find_by_name($1).identifier |
56 | 56 | |
57 | + when /^(.+)'s page of product (.*)$/ | |
58 | + enterprise = Profile.find_by_name($1) | |
59 | + product = enterprise.products.find_by_name($2) | |
60 | + '/myprofile/%s/manage_products/show/%s' % [enterprise.identifier, product.id] | |
61 | + | |
62 | + when /^(.*)'s products page$/ | |
63 | + '/catalog/%s' % Profile.find_by_name($1).identifier | |
64 | + | |
57 | 65 | # Add more mappings here. |
58 | 66 | # Here is a more fancy example: |
59 | 67 | # | ... | ... |
public/designs/templates/leftbar/stylesheets/style.css
public/designs/templates/rightbar/stylesheets/style.css
public/javascripts/application.js
... | ... | @@ -138,3 +138,58 @@ function update_loading(message) { |
138 | 138 | function redirect_to(url) { |
139 | 139 | document.location=url; |
140 | 140 | } |
141 | + | |
142 | +/* Products edition */ | |
143 | + | |
144 | +function numbersonly(e, separator) { | |
145 | + var key; | |
146 | + var keychar; | |
147 | + | |
148 | + if (window.event) { | |
149 | + key = window.event.keyCode; | |
150 | + } | |
151 | + else if (e) { | |
152 | + key = e.which; | |
153 | + } | |
154 | + else { | |
155 | + return true; | |
156 | + } | |
157 | + keychar = String.fromCharCode(key); | |
158 | + | |
159 | + if ((key==null) || (key==0) || (key==8) || (key==9) || (key==13) || (key==27) ) { | |
160 | + return true; | |
161 | + } | |
162 | + else if ((("0123456789").indexOf(keychar) > -1)) { | |
163 | + return true; | |
164 | + } | |
165 | + else if (keychar == separator) { | |
166 | + return true; | |
167 | + } | |
168 | + else | |
169 | + return false; | |
170 | +} | |
171 | + | |
172 | +// transform all element with class ui_button in a jQuery UI button | |
173 | +function render_jquery_ui_buttons(element_id) { | |
174 | + if (element_id) { | |
175 | + element_id = '#' + element_id | |
176 | + jQuery(element_id).button({ | |
177 | + icons: { | |
178 | + primary: jQuery(element_id).attr('data-primary-icon'), | |
179 | + secondary: jQuery(element_id).attr('data-secondary-icon') | |
180 | + } | |
181 | + } | |
182 | + ) | |
183 | + } | |
184 | + else { | |
185 | + jQuery('.ui_button').each(function() { | |
186 | + jQuery(this).button({ | |
187 | + icons: { | |
188 | + primary: this.getAttribute('data-primary-icon'), | |
189 | + secondary: this.getAttribute('data-secondary-icon') | |
190 | + } | |
191 | + } | |
192 | + ) | |
193 | + }) | |
194 | + } | |
195 | +} | ... | ... |
... | ... | @@ -0,0 +1,675 @@ |
1 | +/*! | |
2 | + * jQuery Form Plugin | |
3 | + * version: 2.43 (12-MAR-2010) | |
4 | + * @requires jQuery v1.3.2 or later | |
5 | + * | |
6 | + * Examples and documentation at: http://malsup.com/jquery/form/ | |
7 | + * Dual licensed under the MIT and GPL licenses: | |
8 | + * http://www.opensource.org/licenses/mit-license.php | |
9 | + * http://www.gnu.org/licenses/gpl.html | |
10 | + */ | |
11 | +;(function($) { | |
12 | + | |
13 | +/* | |
14 | + Usage Note: | |
15 | + ----------- | |
16 | + Do not use both ajaxSubmit and ajaxForm on the same form. These | |
17 | + functions are intended to be exclusive. Use ajaxSubmit if you want | |
18 | + to bind your own submit handler to the form. For example, | |
19 | + | |
20 | + $(document).ready(function() { | |
21 | + $('#myForm').bind('submit', function() { | |
22 | + $(this).ajaxSubmit({ | |
23 | + target: '#output' | |
24 | + }); | |
25 | + return false; // <-- important! | |
26 | + }); | |
27 | + }); | |
28 | + | |
29 | + Use ajaxForm when you want the plugin to manage all the event binding | |
30 | + for you. For example, | |
31 | + | |
32 | + $(document).ready(function() { | |
33 | + $('#myForm').ajaxForm({ | |
34 | + target: '#output' | |
35 | + }); | |
36 | + }); | |
37 | + | |
38 | + When using ajaxForm, the ajaxSubmit function will be invoked for you | |
39 | + at the appropriate time. | |
40 | +*/ | |
41 | + | |
42 | +/** | |
43 | + * ajaxSubmit() provides a mechanism for immediately submitting | |
44 | + * an HTML form using AJAX. | |
45 | + */ | |
46 | +$.fn.ajaxSubmit = function(options) { | |
47 | + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) | |
48 | + if (!this.length) { | |
49 | + log('ajaxSubmit: skipping submit process - no element selected'); | |
50 | + return this; | |
51 | + } | |
52 | + | |
53 | + if (typeof options == 'function') | |
54 | + options = { success: options }; | |
55 | + | |
56 | + var url = $.trim(this.attr('action')); | |
57 | + if (url) { | |
58 | + // clean url (don't include hash vaue) | |
59 | + url = (url.match(/^([^#]+)/)||[])[1]; | |
60 | + } | |
61 | + url = url || window.location.href || ''; | |
62 | + | |
63 | + options = $.extend({ | |
64 | + url: url, | |
65 | + type: this.attr('method') || 'GET', | |
66 | + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' | |
67 | + }, options || {}); | |
68 | + | |
69 | + // hook for manipulating the form data before it is extracted; | |
70 | + // convenient for use with rich editors like tinyMCE or FCKEditor | |
71 | + var veto = {}; | |
72 | + this.trigger('form-pre-serialize', [this, options, veto]); | |
73 | + if (veto.veto) { | |
74 | + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); | |
75 | + return this; | |
76 | + } | |
77 | + | |
78 | + // provide opportunity to alter form data before it is serialized | |
79 | + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { | |
80 | + log('ajaxSubmit: submit aborted via beforeSerialize callback'); | |
81 | + return this; | |
82 | + } | |
83 | + | |
84 | + var a = this.formToArray(options.semantic); | |
85 | + if (options.data) { | |
86 | + options.extraData = options.data; | |
87 | + for (var n in options.data) { | |
88 | + if(options.data[n] instanceof Array) { | |
89 | + for (var k in options.data[n]) | |
90 | + a.push( { name: n, value: options.data[n][k] } ); | |
91 | + } | |
92 | + else | |
93 | + a.push( { name: n, value: options.data[n] } ); | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + // give pre-submit callback an opportunity to abort the submit | |
98 | + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { | |
99 | + log('ajaxSubmit: submit aborted via beforeSubmit callback'); | |
100 | + return this; | |
101 | + } | |
102 | + | |
103 | + // fire vetoable 'validate' event | |
104 | + this.trigger('form-submit-validate', [a, this, options, veto]); | |
105 | + if (veto.veto) { | |
106 | + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); | |
107 | + return this; | |
108 | + } | |
109 | + | |
110 | + var q = $.param(a); | |
111 | + | |
112 | + if (options.type.toUpperCase() == 'GET') { | |
113 | + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; | |
114 | + options.data = null; // data is null for 'get' | |
115 | + } | |
116 | + else | |
117 | + options.data = q; // data is the query string for 'post' | |
118 | + | |
119 | + var $form = this, callbacks = []; | |
120 | + if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); | |
121 | + if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); | |
122 | + | |
123 | + // perform a load on the target only if dataType is not provided | |
124 | + if (!options.dataType && options.target) { | |
125 | + var oldSuccess = options.success || function(){}; | |
126 | + callbacks.push(function(data) { | |
127 | + var fn = options.replaceTarget ? 'replaceWith' : 'html'; | |
128 | + $(options.target)[fn](data).each(oldSuccess, arguments); | |
129 | + }); | |
130 | + } | |
131 | + else if (options.success) | |
132 | + callbacks.push(options.success); | |
133 | + | |
134 | + options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg | |
135 | + for (var i=0, max=callbacks.length; i < max; i++) | |
136 | + callbacks[i].apply(options, [data, status, xhr || $form, $form]); | |
137 | + }; | |
138 | + | |
139 | + // are there files to upload? | |
140 | + var files = $('input:file', this).fieldValue(); | |
141 | + var found = false; | |
142 | + for (var j=0; j < files.length; j++) | |
143 | + if (files[j]) | |
144 | + found = true; | |
145 | + | |
146 | + var multipart = false; | |
147 | +// var mp = 'multipart/form-data'; | |
148 | +// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); | |
149 | + | |
150 | + // options.iframe allows user to force iframe mode | |
151 | + // 06-NOV-09: now defaulting to iframe mode if file input is detected | |
152 | + if ((files.length && options.iframe !== false) || options.iframe || found || multipart) { | |
153 | + // hack to fix Safari hang (thanks to Tim Molendijk for this) | |
154 | + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d | |
155 | + if (options.closeKeepAlive) | |
156 | + $.get(options.closeKeepAlive, fileUpload); | |
157 | + else | |
158 | + fileUpload(); | |
159 | + } | |
160 | + else | |
161 | + $.ajax(options); | |
162 | + | |
163 | + // fire 'notify' event | |
164 | + this.trigger('form-submit-notify', [this, options]); | |
165 | + return this; | |
166 | + | |
167 | + | |
168 | + // private function for handling file uploads (hat tip to YAHOO!) | |
169 | + function fileUpload() { | |
170 | + var form = $form[0]; | |
171 | + | |
172 | + if ($(':input[name=submit]', form).length) { | |
173 | + alert('Error: Form elements must not be named "submit".'); | |
174 | + return; | |
175 | + } | |
176 | + | |
177 | + var opts = $.extend({}, $.ajaxSettings, options); | |
178 | + var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts); | |
179 | + | |
180 | + var id = 'jqFormIO' + (new Date().getTime()); | |
181 | + var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ opts.iframeSrc +'" onload="(jQuery(this).data(\'form-plugin-onload\'))()" />'); | |
182 | + var io = $io[0]; | |
183 | + | |
184 | + $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); | |
185 | + | |
186 | + var xhr = { // mock object | |
187 | + aborted: 0, | |
188 | + responseText: null, | |
189 | + responseXML: null, | |
190 | + status: 0, | |
191 | + statusText: 'n/a', | |
192 | + getAllResponseHeaders: function() {}, | |
193 | + getResponseHeader: function() {}, | |
194 | + setRequestHeader: function() {}, | |
195 | + abort: function() { | |
196 | + this.aborted = 1; | |
197 | + $io.attr('src', opts.iframeSrc); // abort op in progress | |
198 | + } | |
199 | + }; | |
200 | + | |
201 | + var g = opts.global; | |
202 | + // trigger ajax global events so that activity/block indicators work like normal | |
203 | + if (g && ! $.active++) $.event.trigger("ajaxStart"); | |
204 | + if (g) $.event.trigger("ajaxSend", [xhr, opts]); | |
205 | + | |
206 | + if (s.beforeSend && s.beforeSend(xhr, s) === false) { | |
207 | + s.global && $.active--; | |
208 | + return; | |
209 | + } | |
210 | + if (xhr.aborted) | |
211 | + return; | |
212 | + | |
213 | + var cbInvoked = false; | |
214 | + var timedOut = 0; | |
215 | + | |
216 | + // add submitting element to data if we know it | |
217 | + var sub = form.clk; | |
218 | + if (sub) { | |
219 | + var n = sub.name; | |
220 | + if (n && !sub.disabled) { | |
221 | + opts.extraData = opts.extraData || {}; | |
222 | + opts.extraData[n] = sub.value; | |
223 | + if (sub.type == "image") { | |
224 | + opts.extraData[n+'.x'] = form.clk_x; | |
225 | + opts.extraData[n+'.y'] = form.clk_y; | |
226 | + } | |
227 | + } | |
228 | + } | |
229 | + | |
230 | + // take a breath so that pending repaints get some cpu time before the upload starts | |
231 | + function doSubmit() { | |
232 | + // make sure form attrs are set | |
233 | + var t = $form.attr('target'), a = $form.attr('action'); | |
234 | + | |
235 | + // update form attrs in IE friendly way | |
236 | + form.setAttribute('target',id); | |
237 | + if (form.getAttribute('method') != 'POST') | |
238 | + form.setAttribute('method', 'POST'); | |
239 | + if (form.getAttribute('action') != opts.url) | |
240 | + form.setAttribute('action', opts.url); | |
241 | + | |
242 | + // ie borks in some cases when setting encoding | |
243 | + if (! opts.skipEncodingOverride) { | |
244 | + $form.attr({ | |
245 | + encoding: 'multipart/form-data', | |
246 | + enctype: 'multipart/form-data' | |
247 | + }); | |
248 | + } | |
249 | + | |
250 | + // support timout | |
251 | + if (opts.timeout) | |
252 | + setTimeout(function() { timedOut = true; cb(); }, opts.timeout); | |
253 | + | |
254 | + // add "extra" data to form if provided in options | |
255 | + var extraInputs = []; | |
256 | + try { | |
257 | + if (opts.extraData) | |
258 | + for (var n in opts.extraData) | |
259 | + extraInputs.push( | |
260 | + $('<input type="hidden" name="'+n+'" value="'+opts.extraData[n]+'" />') | |
261 | + .appendTo(form)[0]); | |
262 | + | |
263 | + // add iframe to doc and submit the form | |
264 | + $io.appendTo('body'); | |
265 | + $io.data('form-plugin-onload', cb); | |
266 | + form.submit(); | |
267 | + } | |
268 | + finally { | |
269 | + // reset attrs and remove "extra" input elements | |
270 | + form.setAttribute('action',a); | |
271 | + t ? form.setAttribute('target', t) : $form.removeAttr('target'); | |
272 | + $(extraInputs).remove(); | |
273 | + } | |
274 | + }; | |
275 | + | |
276 | + if (opts.forceSync) | |
277 | + doSubmit(); | |
278 | + else | |
279 | + setTimeout(doSubmit, 10); // this lets dom updates render | |
280 | + | |
281 | + var domCheckCount = 100; | |
282 | + | |
283 | + function cb() { | |
284 | + if (cbInvoked) | |
285 | + return; | |
286 | + | |
287 | + var ok = true; | |
288 | + try { | |
289 | + if (timedOut) throw 'timeout'; | |
290 | + // extract the server response from the iframe | |
291 | + var data, doc; | |
292 | + | |
293 | + doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; | |
294 | + | |
295 | + var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); | |
296 | + log('isXml='+isXml); | |
297 | + if (!isXml && (doc.body == null || doc.body.innerHTML == '')) { | |
298 | + if (--domCheckCount) { | |
299 | + // in some browsers (Opera) the iframe DOM is not always traversable when | |
300 | + // the onload callback fires, so we loop a bit to accommodate | |
301 | + log('requeing onLoad callback, DOM not available'); | |
302 | + setTimeout(cb, 250); | |
303 | + return; | |
304 | + } | |
305 | + log('Could not access iframe DOM after 100 tries.'); | |
306 | + return; | |
307 | + } | |
308 | + | |
309 | + log('response detected'); | |
310 | + cbInvoked = true; | |
311 | + xhr.responseText = doc.body ? doc.body.innerHTML : null; | |
312 | + xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; | |
313 | + xhr.getResponseHeader = function(header){ | |
314 | + var headers = {'content-type': opts.dataType}; | |
315 | + return headers[header]; | |
316 | + }; | |
317 | + | |
318 | + if (opts.dataType == 'json' || opts.dataType == 'script') { | |
319 | + // see if user embedded response in textarea | |
320 | + var ta = doc.getElementsByTagName('textarea')[0]; | |
321 | + if (ta) | |
322 | + xhr.responseText = ta.value; | |
323 | + else { | |
324 | + // account for browsers injecting pre around json response | |
325 | + var pre = doc.getElementsByTagName('pre')[0]; | |
326 | + if (pre) | |
327 | + xhr.responseText = pre.innerHTML; | |
328 | + } | |
329 | + } | |
330 | + else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { | |
331 | + xhr.responseXML = toXml(xhr.responseText); | |
332 | + } | |
333 | + data = $.httpData(xhr, opts.dataType); | |
334 | + } | |
335 | + catch(e){ | |
336 | + log('error caught:',e); | |
337 | + ok = false; | |
338 | + xhr.error = e; | |
339 | + $.handleError(opts, xhr, 'error', e); | |
340 | + } | |
341 | + | |
342 | + // ordering of these callbacks/triggers is odd, but that's how $.ajax does it | |
343 | + if (ok) { | |
344 | + opts.success(data, 'success'); | |
345 | + if (g) $.event.trigger("ajaxSuccess", [xhr, opts]); | |
346 | + } | |
347 | + if (g) $.event.trigger("ajaxComplete", [xhr, opts]); | |
348 | + if (g && ! --$.active) $.event.trigger("ajaxStop"); | |
349 | + if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error'); | |
350 | + | |
351 | + // clean up | |
352 | + setTimeout(function() { | |
353 | + $io.removeData('form-plugin-onload'); | |
354 | + $io.remove(); | |
355 | + xhr.responseXML = null; | |
356 | + }, 100); | |
357 | + }; | |
358 | + | |
359 | + function toXml(s, doc) { | |
360 | + if (window.ActiveXObject) { | |
361 | + doc = new ActiveXObject('Microsoft.XMLDOM'); | |
362 | + doc.async = 'false'; | |
363 | + doc.loadXML(s); | |
364 | + } | |
365 | + else | |
366 | + doc = (new DOMParser()).parseFromString(s, 'text/xml'); | |
367 | + return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null; | |
368 | + }; | |
369 | + }; | |
370 | +}; | |
371 | + | |
372 | +/** | |
373 | + * ajaxForm() provides a mechanism for fully automating form submission. | |
374 | + * | |
375 | + * The advantages of using this method instead of ajaxSubmit() are: | |
376 | + * | |
377 | + * 1: This method will include coordinates for <input type="image" /> elements (if the element | |
378 | + * is used to submit the form). | |
379 | + * 2. This method will include the submit element's name/value data (for the element that was | |
380 | + * used to submit the form). | |
381 | + * 3. This method binds the submit() method to the form for you. | |
382 | + * | |
383 | + * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely | |
384 | + * passes the options argument along after properly binding events for submit elements and | |
385 | + * the form itself. | |
386 | + */ | |
387 | +$.fn.ajaxForm = function(options) { | |
388 | + return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) { | |
389 | + e.preventDefault(); | |
390 | + $(this).ajaxSubmit(options); | |
391 | + }).bind('click.form-plugin', function(e) { | |
392 | + var target = e.target; | |
393 | + var $el = $(target); | |
394 | + if (!($el.is(":submit,input:image"))) { | |
395 | + // is this a child element of the submit el? (ex: a span within a button) | |
396 | + var t = $el.closest(':submit'); | |
397 | + if (t.length == 0) | |
398 | + return; | |
399 | + target = t[0]; | |
400 | + } | |
401 | + var form = this; | |
402 | + form.clk = target; | |
403 | + if (target.type == 'image') { | |
404 | + if (e.offsetX != undefined) { | |
405 | + form.clk_x = e.offsetX; | |
406 | + form.clk_y = e.offsetY; | |
407 | + } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin | |
408 | + var offset = $el.offset(); | |
409 | + form.clk_x = e.pageX - offset.left; | |
410 | + form.clk_y = e.pageY - offset.top; | |
411 | + } else { | |
412 | + form.clk_x = e.pageX - target.offsetLeft; | |
413 | + form.clk_y = e.pageY - target.offsetTop; | |
414 | + } | |
415 | + } | |
416 | + // clear form vars | |
417 | + setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); | |
418 | + }); | |
419 | +}; | |
420 | + | |
421 | +// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm | |
422 | +$.fn.ajaxFormUnbind = function() { | |
423 | + return this.unbind('submit.form-plugin click.form-plugin'); | |
424 | +}; | |
425 | + | |
426 | +/** | |
427 | + * formToArray() gathers form element data into an array of objects that can | |
428 | + * be passed to any of the following ajax functions: $.get, $.post, or load. | |
429 | + * Each object in the array has both a 'name' and 'value' property. An example of | |
430 | + * an array for a simple login form might be: | |
431 | + * | |
432 | + * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] | |
433 | + * | |
434 | + * It is this array that is passed to pre-submit callback functions provided to the | |
435 | + * ajaxSubmit() and ajaxForm() methods. | |
436 | + */ | |
437 | +$.fn.formToArray = function(semantic) { | |
438 | + var a = []; | |
439 | + if (this.length == 0) return a; | |
440 | + | |
441 | + var form = this[0]; | |
442 | + var els = semantic ? form.getElementsByTagName('*') : form.elements; | |
443 | + if (!els) return a; | |
444 | + for(var i=0, max=els.length; i < max; i++) { | |
445 | + var el = els[i]; | |
446 | + var n = el.name; | |
447 | + if (!n) continue; | |
448 | + | |
449 | + if (semantic && form.clk && el.type == "image") { | |
450 | + // handle image inputs on the fly when semantic == true | |
451 | + if(!el.disabled && form.clk == el) { | |
452 | + a.push({name: n, value: $(el).val()}); | |
453 | + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); | |
454 | + } | |
455 | + continue; | |
456 | + } | |
457 | + | |
458 | + var v = $.fieldValue(el, true); | |
459 | + if (v && v.constructor == Array) { | |
460 | + for(var j=0, jmax=v.length; j < jmax; j++) | |
461 | + a.push({name: n, value: v[j]}); | |
462 | + } | |
463 | + else if (v !== null && typeof v != 'undefined') | |
464 | + a.push({name: n, value: v}); | |
465 | + } | |
466 | + | |
467 | + if (!semantic && form.clk) { | |
468 | + // input type=='image' are not found in elements array! handle it here | |
469 | + var $input = $(form.clk), input = $input[0], n = input.name; | |
470 | + if (n && !input.disabled && input.type == 'image') { | |
471 | + a.push({name: n, value: $input.val()}); | |
472 | + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); | |
473 | + } | |
474 | + } | |
475 | + return a; | |
476 | +}; | |
477 | + | |
478 | +/** | |
479 | + * Serializes form data into a 'submittable' string. This method will return a string | |
480 | + * in the format: name1=value1&name2=value2 | |
481 | + */ | |
482 | +$.fn.formSerialize = function(semantic) { | |
483 | + //hand off to jQuery.param for proper encoding | |
484 | + return $.param(this.formToArray(semantic)); | |
485 | +}; | |
486 | + | |
487 | +/** | |
488 | + * Serializes all field elements in the jQuery object into a query string. | |
489 | + * This method will return a string in the format: name1=value1&name2=value2 | |
490 | + */ | |
491 | +$.fn.fieldSerialize = function(successful) { | |
492 | + var a = []; | |
493 | + this.each(function() { | |
494 | + var n = this.name; | |
495 | + if (!n) return; | |
496 | + var v = $.fieldValue(this, successful); | |
497 | + if (v && v.constructor == Array) { | |
498 | + for (var i=0,max=v.length; i < max; i++) | |
499 | + a.push({name: n, value: v[i]}); | |
500 | + } | |
501 | + else if (v !== null && typeof v != 'undefined') | |
502 | + a.push({name: this.name, value: v}); | |
503 | + }); | |
504 | + //hand off to jQuery.param for proper encoding | |
505 | + return $.param(a); | |
506 | +}; | |
507 | + | |
508 | +/** | |
509 | + * Returns the value(s) of the element in the matched set. For example, consider the following form: | |
510 | + * | |
511 | + * <form><fieldset> | |
512 | + * <input name="A" type="text" /> | |
513 | + * <input name="A" type="text" /> | |
514 | + * <input name="B" type="checkbox" value="B1" /> | |
515 | + * <input name="B" type="checkbox" value="B2"/> | |
516 | + * <input name="C" type="radio" value="C1" /> | |
517 | + * <input name="C" type="radio" value="C2" /> | |
518 | + * </fieldset></form> | |
519 | + * | |
520 | + * var v = $(':text').fieldValue(); | |
521 | + * // if no values are entered into the text inputs | |
522 | + * v == ['',''] | |
523 | + * // if values entered into the text inputs are 'foo' and 'bar' | |
524 | + * v == ['foo','bar'] | |
525 | + * | |
526 | + * var v = $(':checkbox').fieldValue(); | |
527 | + * // if neither checkbox is checked | |
528 | + * v === undefined | |
529 | + * // if both checkboxes are checked | |
530 | + * v == ['B1', 'B2'] | |
531 | + * | |
532 | + * var v = $(':radio').fieldValue(); | |
533 | + * // if neither radio is checked | |
534 | + * v === undefined | |
535 | + * // if first radio is checked | |
536 | + * v == ['C1'] | |
537 | + * | |
538 | + * The successful argument controls whether or not the field element must be 'successful' | |
539 | + * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). | |
540 | + * The default value of the successful argument is true. If this value is false the value(s) | |
541 | + * for each element is returned. | |
542 | + * | |
543 | + * Note: This method *always* returns an array. If no valid value can be determined the | |
544 | + * array will be empty, otherwise it will contain one or more values. | |
545 | + */ | |
546 | +$.fn.fieldValue = function(successful) { | |
547 | + for (var val=[], i=0, max=this.length; i < max; i++) { | |
548 | + var el = this[i]; | |
549 | + var v = $.fieldValue(el, successful); | |
550 | + if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) | |
551 | + continue; | |
552 | + v.constructor == Array ? $.merge(val, v) : val.push(v); | |
553 | + } | |
554 | + return val; | |
555 | +}; | |
556 | + | |
557 | +/** | |
558 | + * Returns the value of the field element. | |
559 | + */ | |
560 | +$.fieldValue = function(el, successful) { | |
561 | + var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); | |
562 | + if (typeof successful == 'undefined') successful = true; | |
563 | + | |
564 | + if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || | |
565 | + (t == 'checkbox' || t == 'radio') && !el.checked || | |
566 | + (t == 'submit' || t == 'image') && el.form && el.form.clk != el || | |
567 | + tag == 'select' && el.selectedIndex == -1)) | |
568 | + return null; | |
569 | + | |
570 | + if (tag == 'select') { | |
571 | + var index = el.selectedIndex; | |
572 | + if (index < 0) return null; | |
573 | + var a = [], ops = el.options; | |
574 | + var one = (t == 'select-one'); | |
575 | + var max = (one ? index+1 : ops.length); | |
576 | + for(var i=(one ? index : 0); i < max; i++) { | |
577 | + var op = ops[i]; | |
578 | + if (op.selected) { | |
579 | + var v = op.value; | |
580 | + if (!v) // extra pain for IE... | |
581 | + v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; | |
582 | + if (one) return v; | |
583 | + a.push(v); | |
584 | + } | |
585 | + } | |
586 | + return a; | |
587 | + } | |
588 | + return el.value; | |
589 | +}; | |
590 | + | |
591 | +/** | |
592 | + * Clears the form data. Takes the following actions on the form's input fields: | |
593 | + * - input text fields will have their 'value' property set to the empty string | |
594 | + * - select elements will have their 'selectedIndex' property set to -1 | |
595 | + * - checkbox and radio inputs will have their 'checked' property set to false | |
596 | + * - inputs of type submit, button, reset, and hidden will *not* be effected | |
597 | + * - button elements will *not* be effected | |
598 | + */ | |
599 | +$.fn.clearForm = function() { | |
600 | + return this.each(function() { | |
601 | + $('input,select,textarea', this).clearFields(); | |
602 | + }); | |
603 | +}; | |
604 | + | |
605 | +/** | |
606 | + * Clears the selected form elements. | |
607 | + */ | |
608 | +$.fn.clearFields = $.fn.clearInputs = function() { | |
609 | + return this.each(function() { | |
610 | + var t = this.type, tag = this.tagName.toLowerCase(); | |
611 | + if (t == 'text' || t == 'password' || tag == 'textarea') | |
612 | + this.value = ''; | |
613 | + else if (t == 'checkbox' || t == 'radio') | |
614 | + this.checked = false; | |
615 | + else if (tag == 'select') | |
616 | + this.selectedIndex = -1; | |
617 | + }); | |
618 | +}; | |
619 | + | |
620 | +/** | |
621 | + * Resets the form data. Causes all form elements to be reset to their original value. | |
622 | + */ | |
623 | +$.fn.resetForm = function() { | |
624 | + return this.each(function() { | |
625 | + // guard against an input with the name of 'reset' | |
626 | + // note that IE reports the reset function as an 'object' | |
627 | + if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) | |
628 | + this.reset(); | |
629 | + }); | |
630 | +}; | |
631 | + | |
632 | +/** | |
633 | + * Enables or disables any matching elements. | |
634 | + */ | |
635 | +$.fn.enable = function(b) { | |
636 | + if (b == undefined) b = true; | |
637 | + return this.each(function() { | |
638 | + this.disabled = !b; | |
639 | + }); | |
640 | +}; | |
641 | + | |
642 | +/** | |
643 | + * Checks/unchecks any matching checkboxes or radio buttons and | |
644 | + * selects/deselects and matching option elements. | |
645 | + */ | |
646 | +$.fn.selected = function(select) { | |
647 | + if (select == undefined) select = true; | |
648 | + return this.each(function() { | |
649 | + var t = this.type; | |
650 | + if (t == 'checkbox' || t == 'radio') | |
651 | + this.checked = select; | |
652 | + else if (this.tagName.toLowerCase() == 'option') { | |
653 | + var $sel = $(this).parent('select'); | |
654 | + if (select && $sel[0] && $sel[0].type == 'select-one') { | |
655 | + // deselect all other options | |
656 | + $sel.find('option').selected(false); | |
657 | + } | |
658 | + this.selected = select; | |
659 | + } | |
660 | + }); | |
661 | +}; | |
662 | + | |
663 | +// helper fn for console logging | |
664 | +// set $.fn.ajaxSubmit.debug to true to enable debug logging | |
665 | +function log() { | |
666 | + if ($.fn.ajaxSubmit.debug) { | |
667 | + var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); | |
668 | + if (window.console && window.console.log) | |
669 | + window.console.log(msg); | |
670 | + else if (window.opera && window.opera.postError) | |
671 | + window.opera.postError(msg); | |
672 | + } | |
673 | +}; | |
674 | + | |
675 | +})(jQuery); | ... | ... |
public/stylesheets/application.css
... | ... | @@ -97,7 +97,7 @@ div#profile-disabled { |
97 | 97 | padding-left: 60px; |
98 | 98 | min-height: 40px; |
99 | 99 | width: 400px; |
100 | - background: url("../images/icons-app/alert.png") no-repeat 5px #ffffa9; | |
100 | + background: url('/images/icons-app/alert.png') no-repeat 5px #ffffa9; | |
101 | 101 | } |
102 | 102 | |
103 | 103 | div#profile-disabled .unlock-button{ |
... | ... | @@ -2503,20 +2503,158 @@ div#activation_enterprise div { |
2503 | 2503 | |
2504 | 2504 | /* * * Show Product * * * * * * * * * * * * */ |
2505 | 2505 | |
2506 | -#show_product .product-pic { | |
2506 | +.controller-catalog #show_product .product-pic { | |
2507 | + border: 1px solid #D3D7CF; | |
2508 | +} | |
2509 | + | |
2510 | +#show_product, | |
2511 | +#category-product-edition { | |
2512 | + background-color: transparent; | |
2513 | + position: relative; | |
2514 | + padding: 5px; | |
2515 | + -moz-border-radius: 5px; | |
2516 | + -webkit-border-radius: 5px; | |
2517 | +} | |
2518 | + | |
2519 | +#show_product h2, | |
2520 | +#category-product-edition h2 { | |
2521 | + margin-top: 0px; | |
2522 | +} | |
2523 | + | |
2524 | +#show_product .field-value { | |
2525 | + font-weight: bold; | |
2526 | +} | |
2527 | + | |
2528 | +#product-category, | |
2529 | +.product-category-hierarchy { | |
2530 | + margin-top: 40px; | |
2531 | + margin-bottom: 12px; | |
2532 | + padding-left: 7px; | |
2533 | +} | |
2534 | + | |
2535 | +#product-category { | |
2536 | + height: 18px; | |
2537 | +} | |
2538 | + | |
2539 | +#product-category p { | |
2540 | + display: inline; | |
2541 | +} | |
2542 | + | |
2543 | +#category-product-edition { | |
2544 | + padding-left: 10px; | |
2545 | + padding-right: 10px; | |
2546 | +} | |
2547 | + | |
2548 | +#display-product-name, | |
2549 | +#display-product-category { | |
2507 | 2550 | float: left; |
2508 | - margin-right: 15px; | |
2509 | - border: 1px solid #444; | |
2510 | - padding: 2px; | |
2511 | - background: #FFF; | |
2512 | 2551 | } |
2513 | 2552 | |
2514 | -#show_product .product_category { | |
2553 | +#product-details { | |
2515 | 2554 | padding-top: 10px; |
2555 | + padding-bottom: 10px; | |
2556 | + position: relative; | |
2557 | +} | |
2558 | + | |
2559 | +#product-name h2 { | |
2560 | + display: inline; | |
2561 | +} | |
2562 | + | |
2563 | +#product_name { | |
2564 | + width: 90%; | |
2565 | +} | |
2566 | + | |
2567 | +#edit-product-name { | |
2568 | + margin-top: 10px; | |
2569 | +} | |
2570 | + | |
2571 | +#product-name, | |
2572 | +#product-details { | |
2573 | + position: relative; | |
2516 | 2574 | clear: left; |
2517 | 2575 | } |
2518 | 2576 | |
2577 | +#display-product-info { | |
2578 | + left: 290px; | |
2579 | + top: 10px; | |
2580 | + width: 360px; | |
2581 | + text-align: left; | |
2582 | + position: absolute; | |
2583 | + overflow: hidden; | |
2584 | +} | |
2585 | + | |
2586 | +#product-info-form { | |
2587 | + margin-top: 20px; | |
2588 | +} | |
2519 | 2589 | |
2590 | +#edit-product-category { | |
2591 | + padding: 15px 5px 10px; | |
2592 | +} | |
2593 | + | |
2594 | +#product-info .field-name { | |
2595 | + margin-top: 5px; | |
2596 | + margin-bottom: 15px; | |
2597 | +} | |
2598 | + | |
2599 | +#product-info .type-text input, | |
2600 | +#product-info select { | |
2601 | + width: 150px; | |
2602 | +} | |
2603 | + | |
2604 | +#product-info .section-title { | |
2605 | + display: none; | |
2606 | +} | |
2607 | + | |
2608 | +#product-qualifiers { | |
2609 | + padding-left: 0px; | |
2610 | +} | |
2611 | + | |
2612 | +#product-qualifiers li { | |
2613 | + list-style: none; | |
2614 | +} | |
2615 | + | |
2616 | +#edit-product-button-ui-info { | |
2617 | + margin-top: 40px; | |
2618 | +} | |
2619 | + | |
2620 | +#product-image { | |
2621 | + text-align: center; | |
2622 | + padding: 10px; | |
2623 | + width: 250px; | |
2624 | + margin-right: 10px; | |
2625 | + margin-bottom: 5px; | |
2626 | + border: 1px solid #AAA; | |
2627 | +} | |
2628 | + | |
2629 | +#product-image p { | |
2630 | + font-size: 11px; | |
2631 | + font-style: italic; | |
2632 | + margin-top: 0px; | |
2633 | + color: #555; | |
2634 | +} | |
2635 | + | |
2636 | +#display-product-image { | |
2637 | + margin-bottom: 10px; | |
2638 | + overflow: hidden; | |
2639 | +} | |
2640 | + | |
2641 | +#edit-product-image { | |
2642 | + position: relative; | |
2643 | + margin-top: 5px; | |
2644 | +} | |
2645 | + | |
2646 | +#product-qualifiers-list { | |
2647 | + padding: 0px; | |
2648 | +} | |
2649 | + | |
2650 | +#product-qualifiers-list li { | |
2651 | + list-style: none; | |
2652 | +} | |
2653 | + | |
2654 | +#product-qualifiers-list .product-qualifier-title, | |
2655 | +#product-qualifiers-list .product-certifier-title { | |
2656 | + margin-right: 20px; | |
2657 | +} | |
2520 | 2658 | /* ==> public/stylesheets/controller_cms.css <== */ |
2521 | 2659 | |
2522 | 2660 | .controller-cms #article_types li { |
... | ... | @@ -3007,7 +3145,7 @@ h1#agenda-title { |
3007 | 3145 | #new_product_title { |
3008 | 3146 | text-align: center; |
3009 | 3147 | } |
3010 | -#new_product_form { | |
3148 | +#product_category_form { | |
3011 | 3149 | border: 1px solid #AABB88; |
3012 | 3150 | -moz-border-radius: 5px; |
3013 | 3151 | -webkit-border-radius: 5px; |
... | ... | @@ -3063,7 +3201,7 @@ h1#agenda-title { |
3063 | 3201 | display: block; |
3064 | 3202 | } |
3065 | 3203 | #hierarchy_navigation { |
3066 | - min-height: 1em; | |
3204 | + min-height: 1.3em; | |
3067 | 3205 | } |
3068 | 3206 | .msie #hierarchy_navigation { |
3069 | 3207 | font-size: small; |
... | ... | @@ -3903,7 +4041,8 @@ h1#agenda-title { |
3903 | 4041 | /* jquery.ui custom styles */ |
3904 | 4042 | |
3905 | 4043 | .fg-button span { |
3906 | - padding: 0.1em 1em !important; | |
4044 | + padding-top: 0.1em !important; | |
4045 | + padding-bottom: 0.1em !important; | |
3907 | 4046 | } |
3908 | 4047 | |
3909 | 4048 | .treeitem .button{ | ... | ... |
public/stylesheets/jquery.ui/south-street/images/ui-anim_basic_16x16.gif
0 → 100644
1.52 KB
public/stylesheets/jquery.ui/south-street/images/ui-bg_glass_55_fcf0ba_1x400.png
0 → 100644
127 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_gloss-wave_100_ece8da_500x100.png
0 → 100644
2.08 KB
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-hard_100_f5f3e5_1x100.png
0 → 100644
110 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-hard_100_fafaf4_1x100.png
0 → 100644
96 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-hard_15_459e00_1x100.png
0 → 100644
153 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-hard_95_cccccc_1x100.png
0 → 100644
105 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-soft_25_67b021_1x100.png
0 → 100644
124 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_highlight-soft_95_ffedad_1x100.png
0 → 100644
165 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-bg_inset-soft_15_2b2922_1x100.png
0 → 100644
119 Bytes
public/stylesheets/jquery.ui/south-street/images/ui-icons_808080_256x240.png
0 → 100644
4.27 KB
public/stylesheets/jquery.ui/south-street/images/ui-icons_847e71_256x240.png
0 → 100644
4.27 KB
public/stylesheets/jquery.ui/south-street/images/ui-icons_8dc262_256x240.png
0 → 100644
5.23 KB
public/stylesheets/jquery.ui/south-street/images/ui-icons_cd0a0a_256x240.png
0 → 100644
4.27 KB
public/stylesheets/jquery.ui/south-street/images/ui-icons_eeeeee_256x240.png
0 → 100644
4.27 KB
public/stylesheets/jquery.ui/south-street/images/ui-icons_ffffff_256x240.png
0 → 100644
4.27 KB
public/stylesheets/jquery.ui/south-street/jquery-ui-1.8.2.custom.css
0 → 100644
... | ... | @@ -0,0 +1,489 @@ |
1 | +/* | |
2 | +* jQuery UI CSS Framework | |
3 | +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) | |
4 | +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
5 | +*/ | |
6 | + | |
7 | +/* Layout helpers | |
8 | +----------------------------------*/ | |
9 | +.ui-helper-hidden { display: none; } | |
10 | +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } | |
11 | +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } | |
12 | +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } | |
13 | +.ui-helper-clearfix { display: inline-block; } | |
14 | +/* required comment for clearfix to work in Opera \*/ | |
15 | +* html .ui-helper-clearfix { height:1%; } | |
16 | +.ui-helper-clearfix { display:block; } | |
17 | +/* end clearfix */ | |
18 | +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } | |
19 | + | |
20 | + | |
21 | +/* Interaction Cues | |
22 | +----------------------------------*/ | |
23 | +.ui-state-disabled { cursor: default !important; } | |
24 | + | |
25 | + | |
26 | +/* Icons | |
27 | +----------------------------------*/ | |
28 | + | |
29 | +/* states and images */ | |
30 | +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } | |
31 | + | |
32 | + | |
33 | +/* Misc visuals | |
34 | +----------------------------------*/ | |
35 | + | |
36 | +/* Overlays */ | |
37 | +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } | |
38 | + | |
39 | + | |
40 | +/* | |
41 | +* jQuery UI CSS Framework | |
42 | +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) | |
43 | +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
44 | +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=segoe%20ui,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=ece8da&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=100&borderColorHeader=d4ccb0&fcHeader=433f38&iconColorHeader=847e71&bgColorContent=f5f3e5&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=dfd9c3&fcContent=312e25&iconColorContent=808080&bgColorDefault=459e00&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=15&borderColorDefault=327E04&fcDefault=ffffff&iconColorDefault=eeeeee&bgColorHover=67b021&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=25&borderColorHover=327E04&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=fafaf4&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=100&borderColorActive=d4ccb0&fcActive=459e00&iconColorActive=8DC262&bgColorHighlight=fcf0ba&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=e8e1b5&fcHighlight=363636&iconColorHighlight=8DC262&bgColorError=ffedad&bgTextureError=03_highlight_soft.png&bgImgOpacityError=95&borderColorError=e3a345&fcError=cd5c0a&iconColorError=cd0a0a&bgColorOverlay=2b2922&bgTextureOverlay=05_inset_soft.png&bgImgOpacityOverlay=15&opacityOverlay=90&bgColorShadow=cccccc&bgTextureShadow=04_highlight_hard.png&bgImgOpacityShadow=95&opacityShadow=20&thicknessShadow=12px&offsetTopShadow=-12px&offsetLeftShadow=-12px&cornerRadiusShadow=10px | |
45 | +*/ | |
46 | + | |
47 | + | |
48 | +/* Component containers | |
49 | +----------------------------------*/ | |
50 | +.ui-widget { font-family: segoe ui, Arial, sans-serif; font-size: 1.1em; } | |
51 | +.ui-widget .ui-widget { font-size: 1em; } | |
52 | +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: segoe ui, Arial, sans-serif; font-size: 1em; } | |
53 | +.ui-widget-content { border: 1px solid #dfd9c3; background: #f5f3e5 url(images/ui-bg_highlight-hard_100_f5f3e5_1x100.png) 50% top repeat-x; color: #312e25; } | |
54 | +.ui-widget-content a { color: #312e25; } | |
55 | +.ui-widget-header { border: 1px solid #d4ccb0; background: #ece8da url(images/ui-bg_gloss-wave_100_ece8da_500x100.png) 50% 50% repeat-x; color: #433f38; font-weight: bold; } | |
56 | +.ui-widget-header a { color: #433f38; } | |
57 | + | |
58 | +/* Interaction states | |
59 | +----------------------------------*/ | |
60 | +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #327e04; background: #459e00 url(images/ui-bg_highlight-hard_15_459e00_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; } | |
61 | +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; } | |
62 | +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #327e04; background: #67b021 url(images/ui-bg_highlight-soft_25_67b021_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; } | |
63 | +.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; } | |
64 | +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #d4ccb0; background: #fafaf4 url(images/ui-bg_highlight-hard_100_fafaf4_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #459e00; } | |
65 | +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #459e00; text-decoration: none; } | |
66 | +.ui-widget :active { outline: none; } | |
67 | + | |
68 | +/* Interaction Cues | |
69 | +----------------------------------*/ | |
70 | +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #e8e1b5; background: #fcf0ba url(images/ui-bg_glass_55_fcf0ba_1x400.png) 50% 50% repeat-x; color: #363636; } | |
71 | +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } | |
72 | +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #e3a345; background: #ffedad url(images/ui-bg_highlight-soft_95_ffedad_1x100.png) 50% top repeat-x; color: #cd5c0a; } | |
73 | +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd5c0a; } | |
74 | +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd5c0a; } | |
75 | +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } | |
76 | +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } | |
77 | +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } | |
78 | + | |
79 | +/* Icons | |
80 | +----------------------------------*/ | |
81 | + | |
82 | +/* states and images */ | |
83 | +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_808080_256x240.png); } | |
84 | +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_808080_256x240.png); } | |
85 | +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_847e71_256x240.png); } | |
86 | +.ui-state-default .ui-icon { background-image: url(images/ui-icons_eeeeee_256x240.png); } | |
87 | +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } | |
88 | +.ui-state-active .ui-icon {background-image: url(images/ui-icons_8dc262_256x240.png); } | |
89 | +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_8dc262_256x240.png); } | |
90 | +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } | |
91 | + | |
92 | +/* positioning */ | |
93 | +.ui-icon-carat-1-n { background-position: 0 0; } | |
94 | +.ui-icon-carat-1-ne { background-position: -16px 0; } | |
95 | +.ui-icon-carat-1-e { background-position: -32px 0; } | |
96 | +.ui-icon-carat-1-se { background-position: -48px 0; } | |
97 | +.ui-icon-carat-1-s { background-position: -64px 0; } | |
98 | +.ui-icon-carat-1-sw { background-position: -80px 0; } | |
99 | +.ui-icon-carat-1-w { background-position: -96px 0; } | |
100 | +.ui-icon-carat-1-nw { background-position: -112px 0; } | |
101 | +.ui-icon-carat-2-n-s { background-position: -128px 0; } | |
102 | +.ui-icon-carat-2-e-w { background-position: -144px 0; } | |
103 | +.ui-icon-triangle-1-n { background-position: 0 -16px; } | |
104 | +.ui-icon-triangle-1-ne { background-position: -16px -16px; } | |
105 | +.ui-icon-triangle-1-e { background-position: -32px -16px; } | |
106 | +.ui-icon-triangle-1-se { background-position: -48px -16px; } | |
107 | +.ui-icon-triangle-1-s { background-position: -64px -16px; } | |
108 | +.ui-icon-triangle-1-sw { background-position: -80px -16px; } | |
109 | +.ui-icon-triangle-1-w { background-position: -96px -16px; } | |
110 | +.ui-icon-triangle-1-nw { background-position: -112px -16px; } | |
111 | +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } | |
112 | +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } | |
113 | +.ui-icon-arrow-1-n { background-position: 0 -32px; } | |
114 | +.ui-icon-arrow-1-ne { background-position: -16px -32px; } | |
115 | +.ui-icon-arrow-1-e { background-position: -32px -32px; } | |
116 | +.ui-icon-arrow-1-se { background-position: -48px -32px; } | |
117 | +.ui-icon-arrow-1-s { background-position: -64px -32px; } | |
118 | +.ui-icon-arrow-1-sw { background-position: -80px -32px; } | |
119 | +.ui-icon-arrow-1-w { background-position: -96px -32px; } | |
120 | +.ui-icon-arrow-1-nw { background-position: -112px -32px; } | |
121 | +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } | |
122 | +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } | |
123 | +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } | |
124 | +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } | |
125 | +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } | |
126 | +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } | |
127 | +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } | |
128 | +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } | |
129 | +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } | |
130 | +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } | |
131 | +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } | |
132 | +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } | |
133 | +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } | |
134 | +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } | |
135 | +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } | |
136 | +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } | |
137 | +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } | |
138 | +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } | |
139 | +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } | |
140 | +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } | |
141 | +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } | |
142 | +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } | |
143 | +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } | |
144 | +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } | |
145 | +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } | |
146 | +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } | |
147 | +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } | |
148 | +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } | |
149 | +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } | |
150 | +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } | |
151 | +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } | |
152 | +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } | |
153 | +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } | |
154 | +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } | |
155 | +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } | |
156 | +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } | |
157 | +.ui-icon-arrow-4 { background-position: 0 -80px; } | |
158 | +.ui-icon-arrow-4-diag { background-position: -16px -80px; } | |
159 | +.ui-icon-extlink { background-position: -32px -80px; } | |
160 | +.ui-icon-newwin { background-position: -48px -80px; } | |
161 | +.ui-icon-refresh { background-position: -64px -80px; } | |
162 | +.ui-icon-shuffle { background-position: -80px -80px; } | |
163 | +.ui-icon-transfer-e-w { background-position: -96px -80px; } | |
164 | +.ui-icon-transferthick-e-w { background-position: -112px -80px; } | |
165 | +.ui-icon-folder-collapsed { background-position: 0 -96px; } | |
166 | +.ui-icon-folder-open { background-position: -16px -96px; } | |
167 | +.ui-icon-document { background-position: -32px -96px; } | |
168 | +.ui-icon-document-b { background-position: -48px -96px; } | |
169 | +.ui-icon-note { background-position: -64px -96px; } | |
170 | +.ui-icon-mail-closed { background-position: -80px -96px; } | |
171 | +.ui-icon-mail-open { background-position: -96px -96px; } | |
172 | +.ui-icon-suitcase { background-position: -112px -96px; } | |
173 | +.ui-icon-comment { background-position: -128px -96px; } | |
174 | +.ui-icon-person { background-position: -144px -96px; } | |
175 | +.ui-icon-print { background-position: -160px -96px; } | |
176 | +.ui-icon-trash { background-position: -176px -96px; } | |
177 | +.ui-icon-locked { background-position: -192px -96px; } | |
178 | +.ui-icon-unlocked { background-position: -208px -96px; } | |
179 | +.ui-icon-bookmark { background-position: -224px -96px; } | |
180 | +.ui-icon-tag { background-position: -240px -96px; } | |
181 | +.ui-icon-home { background-position: 0 -112px; } | |
182 | +.ui-icon-flag { background-position: -16px -112px; } | |
183 | +.ui-icon-calendar { background-position: -32px -112px; } | |
184 | +.ui-icon-cart { background-position: -48px -112px; } | |
185 | +.ui-icon-pencil { background-position: -64px -112px; } | |
186 | +.ui-icon-clock { background-position: -80px -112px; } | |
187 | +.ui-icon-disk { background-position: -96px -112px; } | |
188 | +.ui-icon-calculator { background-position: -112px -112px; } | |
189 | +.ui-icon-zoomin { background-position: -128px -112px; } | |
190 | +.ui-icon-zoomout { background-position: -144px -112px; } | |
191 | +.ui-icon-search { background-position: -160px -112px; } | |
192 | +.ui-icon-wrench { background-position: -176px -112px; } | |
193 | +.ui-icon-gear { background-position: -192px -112px; } | |
194 | +.ui-icon-heart { background-position: -208px -112px; } | |
195 | +.ui-icon-star { background-position: -224px -112px; } | |
196 | +.ui-icon-link { background-position: -240px -112px; } | |
197 | +.ui-icon-cancel { background-position: 0 -128px; } | |
198 | +.ui-icon-plus { background-position: -16px -128px; } | |
199 | +.ui-icon-plusthick { background-position: -32px -128px; } | |
200 | +.ui-icon-minus { background-position: -48px -128px; } | |
201 | +.ui-icon-minusthick { background-position: -64px -128px; } | |
202 | +.ui-icon-close { background-position: -80px -128px; } | |
203 | +.ui-icon-closethick { background-position: -96px -128px; } | |
204 | +.ui-icon-key { background-position: -112px -128px; } | |
205 | +.ui-icon-lightbulb { background-position: -128px -128px; } | |
206 | +.ui-icon-scissors { background-position: -144px -128px; } | |
207 | +.ui-icon-clipboard { background-position: -160px -128px; } | |
208 | +.ui-icon-copy { background-position: -176px -128px; } | |
209 | +.ui-icon-contact { background-position: -192px -128px; } | |
210 | +.ui-icon-image { background-position: -208px -128px; } | |
211 | +.ui-icon-video { background-position: -224px -128px; } | |
212 | +.ui-icon-script { background-position: -240px -128px; } | |
213 | +.ui-icon-alert { background-position: 0 -144px; } | |
214 | +.ui-icon-info { background-position: -16px -144px; } | |
215 | +.ui-icon-notice { background-position: -32px -144px; } | |
216 | +.ui-icon-help { background-position: -48px -144px; } | |
217 | +.ui-icon-check { background-position: -64px -144px; } | |
218 | +.ui-icon-bullet { background-position: -80px -144px; } | |
219 | +.ui-icon-radio-off { background-position: -96px -144px; } | |
220 | +.ui-icon-radio-on { background-position: -112px -144px; } | |
221 | +.ui-icon-pin-w { background-position: -128px -144px; } | |
222 | +.ui-icon-pin-s { background-position: -144px -144px; } | |
223 | +.ui-icon-play { background-position: 0 -160px; } | |
224 | +.ui-icon-pause { background-position: -16px -160px; } | |
225 | +.ui-icon-seek-next { background-position: -32px -160px; } | |
226 | +.ui-icon-seek-prev { background-position: -48px -160px; } | |
227 | +.ui-icon-seek-end { background-position: -64px -160px; } | |
228 | +.ui-icon-seek-start { background-position: -80px -160px; } | |
229 | +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ | |
230 | +.ui-icon-seek-first { background-position: -80px -160px; } | |
231 | +.ui-icon-stop { background-position: -96px -160px; } | |
232 | +.ui-icon-eject { background-position: -112px -160px; } | |
233 | +.ui-icon-volume-off { background-position: -128px -160px; } | |
234 | +.ui-icon-volume-on { background-position: -144px -160px; } | |
235 | +.ui-icon-power { background-position: 0 -176px; } | |
236 | +.ui-icon-signal-diag { background-position: -16px -176px; } | |
237 | +.ui-icon-signal { background-position: -32px -176px; } | |
238 | +.ui-icon-battery-0 { background-position: -48px -176px; } | |
239 | +.ui-icon-battery-1 { background-position: -64px -176px; } | |
240 | +.ui-icon-battery-2 { background-position: -80px -176px; } | |
241 | +.ui-icon-battery-3 { background-position: -96px -176px; } | |
242 | +.ui-icon-circle-plus { background-position: 0 -192px; } | |
243 | +.ui-icon-circle-minus { background-position: -16px -192px; } | |
244 | +.ui-icon-circle-close { background-position: -32px -192px; } | |
245 | +.ui-icon-circle-triangle-e { background-position: -48px -192px; } | |
246 | +.ui-icon-circle-triangle-s { background-position: -64px -192px; } | |
247 | +.ui-icon-circle-triangle-w { background-position: -80px -192px; } | |
248 | +.ui-icon-circle-triangle-n { background-position: -96px -192px; } | |
249 | +.ui-icon-circle-arrow-e { background-position: -112px -192px; } | |
250 | +.ui-icon-circle-arrow-s { background-position: -128px -192px; } | |
251 | +.ui-icon-circle-arrow-w { background-position: -144px -192px; } | |
252 | +.ui-icon-circle-arrow-n { background-position: -160px -192px; } | |
253 | +.ui-icon-circle-zoomin { background-position: -176px -192px; } | |
254 | +.ui-icon-circle-zoomout { background-position: -192px -192px; } | |
255 | +.ui-icon-circle-check { background-position: -208px -192px; } | |
256 | +.ui-icon-circlesmall-plus { background-position: 0 -208px; } | |
257 | +.ui-icon-circlesmall-minus { background-position: -16px -208px; } | |
258 | +.ui-icon-circlesmall-close { background-position: -32px -208px; } | |
259 | +.ui-icon-squaresmall-plus { background-position: -48px -208px; } | |
260 | +.ui-icon-squaresmall-minus { background-position: -64px -208px; } | |
261 | +.ui-icon-squaresmall-close { background-position: -80px -208px; } | |
262 | +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } | |
263 | +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } | |
264 | +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } | |
265 | +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } | |
266 | +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } | |
267 | +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } | |
268 | + | |
269 | + | |
270 | +/* Misc visuals | |
271 | +----------------------------------*/ | |
272 | + | |
273 | +/* Corner radius */ | |
274 | +.ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; } | |
275 | +.ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; } | |
276 | +.ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; } | |
277 | +.ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } | |
278 | +.ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; } | |
279 | +.ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } | |
280 | +.ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } | |
281 | +.ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; } | |
282 | +.ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; } | |
283 | + | |
284 | +/* Overlays */ | |
285 | +.ui-widget-overlay { background: #2b2922 url(images/ui-bg_inset-soft_15_2b2922_1x100.png) 50% bottom repeat-x; opacity: .90;filter:Alpha(Opacity=90); } | |
286 | +.ui-widget-shadow { margin: -12px 0 0 -12px; padding: 12px; background: #cccccc url(images/ui-bg_highlight-hard_95_cccccc_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }/* Resizable | |
287 | +----------------------------------*/ | |
288 | +.ui-resizable { position: relative;} | |
289 | +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} | |
290 | +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } | |
291 | +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } | |
292 | +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } | |
293 | +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } | |
294 | +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } | |
295 | +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } | |
296 | +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } | |
297 | +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } | |
298 | +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable | |
299 | +----------------------------------*/ | |
300 | +.ui-selectable-helper { border:1px dotted black } | |
301 | +/* Accordion | |
302 | +----------------------------------*/ | |
303 | +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } | |
304 | +.ui-accordion .ui-accordion-li-fix { display: inline; } | |
305 | +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } | |
306 | +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } | |
307 | +/* IE7-/Win - Fix extra vertical space in lists */ | |
308 | +.ui-accordion a { zoom: 1; } | |
309 | +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } | |
310 | +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } | |
311 | +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } | |
312 | +.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete | |
313 | +----------------------------------*/ | |
314 | +.ui-autocomplete { position: absolute; cursor: default; } | |
315 | +.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; } | |
316 | + | |
317 | +/* workarounds */ | |
318 | +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ | |
319 | + | |
320 | +/* Menu | |
321 | +----------------------------------*/ | |
322 | +.ui-menu { | |
323 | + list-style:none; | |
324 | + padding: 2px; | |
325 | + margin: 0; | |
326 | + display:block; | |
327 | +} | |
328 | +.ui-menu .ui-menu { | |
329 | + margin-top: -3px; | |
330 | +} | |
331 | +.ui-menu .ui-menu-item { | |
332 | + margin:0; | |
333 | + padding: 0; | |
334 | + zoom: 1; | |
335 | + float: left; | |
336 | + clear: left; | |
337 | + width: 100%; | |
338 | +} | |
339 | +.ui-menu .ui-menu-item a { | |
340 | + text-decoration:none; | |
341 | + display:block; | |
342 | + padding:.2em .4em; | |
343 | + line-height:1.5; | |
344 | + zoom:1; | |
345 | +} | |
346 | +.ui-menu .ui-menu-item a.ui-state-hover, | |
347 | +.ui-menu .ui-menu-item a.ui-state-active { | |
348 | + font-weight: normal; | |
349 | + margin: -1px; | |
350 | +} | |
351 | +/* Button | |
352 | +----------------------------------*/ | |
353 | + | |
354 | +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ | |
355 | +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ | |
356 | +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ | |
357 | +.ui-button-icons-only { width: 3.4em; } | |
358 | +button.ui-button-icons-only { width: 3.7em; } | |
359 | + | |
360 | +/*button text element */ | |
361 | +.ui-button .ui-button-text { display: block; line-height: 1.4; } | |
362 | +.ui-button-text-only .ui-button-text { padding: .4em 1em; } | |
363 | +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } | |
364 | +.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } | |
365 | +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } | |
366 | +/* no icon support for input elements, provide padding by default */ | |
367 | +input.ui-button { padding: .4em 1em; } | |
368 | + | |
369 | +/*button icon element(s) */ | |
370 | +.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } | |
371 | +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } | |
372 | +.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } | |
373 | +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } | |
374 | + | |
375 | +/*button sets*/ | |
376 | +.ui-buttonset { margin-right: 7px; } | |
377 | +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } | |
378 | + | |
379 | +/* workarounds */ | |
380 | +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ | |
381 | + | |
382 | + | |
383 | + | |
384 | + | |
385 | + | |
386 | +/* Dialog | |
387 | +----------------------------------*/ | |
388 | +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } | |
389 | +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } | |
390 | +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } | |
391 | +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } | |
392 | +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } | |
393 | +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } | |
394 | +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } | |
395 | +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } | |
396 | +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } | |
397 | +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } | |
398 | +.ui-draggable .ui-dialog-titlebar { cursor: move; } | |
399 | +/* Slider | |
400 | +----------------------------------*/ | |
401 | +.ui-slider { position: relative; text-align: left; } | |
402 | +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } | |
403 | +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } | |
404 | + | |
405 | +.ui-slider-horizontal { height: .8em; } | |
406 | +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } | |
407 | +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } | |
408 | +.ui-slider-horizontal .ui-slider-range-min { left: 0; } | |
409 | +.ui-slider-horizontal .ui-slider-range-max { right: 0; } | |
410 | + | |
411 | +.ui-slider-vertical { width: .8em; height: 100px; } | |
412 | +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } | |
413 | +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } | |
414 | +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } | |
415 | +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs | |
416 | +----------------------------------*/ | |
417 | +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ | |
418 | +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } | |
419 | +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } | |
420 | +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } | |
421 | +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } | |
422 | +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } | |
423 | +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ | |
424 | +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } | |
425 | +.ui-tabs .ui-tabs-hide { display: none !important; } | |
426 | +/* Datepicker | |
427 | +----------------------------------*/ | |
428 | +.ui-datepicker { width: 17em; padding: .2em .2em 0; } | |
429 | +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } | |
430 | +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } | |
431 | +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } | |
432 | +.ui-datepicker .ui-datepicker-prev { left:2px; } | |
433 | +.ui-datepicker .ui-datepicker-next { right:2px; } | |
434 | +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } | |
435 | +.ui-datepicker .ui-datepicker-next-hover { right:1px; } | |
436 | +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } | |
437 | +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } | |
438 | +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } | |
439 | +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} | |
440 | +.ui-datepicker select.ui-datepicker-month, | |
441 | +.ui-datepicker select.ui-datepicker-year { width: 49%;} | |
442 | +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } | |
443 | +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } | |
444 | +.ui-datepicker td { border: 0; padding: 1px; } | |
445 | +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } | |
446 | +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } | |
447 | +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } | |
448 | +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } | |
449 | + | |
450 | +/* with multiple calendars */ | |
451 | +.ui-datepicker.ui-datepicker-multi { width:auto; } | |
452 | +.ui-datepicker-multi .ui-datepicker-group { float:left; } | |
453 | +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } | |
454 | +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } | |
455 | +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } | |
456 | +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } | |
457 | +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } | |
458 | +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } | |
459 | +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } | |
460 | +.ui-datepicker-row-break { clear:both; width:100%; } | |
461 | + | |
462 | +/* RTL support */ | |
463 | +.ui-datepicker-rtl { direction: rtl; } | |
464 | +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } | |
465 | +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } | |
466 | +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } | |
467 | +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } | |
468 | +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } | |
469 | +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } | |
470 | +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } | |
471 | +.ui-datepicker-rtl .ui-datepicker-group { float:right; } | |
472 | +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } | |
473 | +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } | |
474 | + | |
475 | +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ | |
476 | +.ui-datepicker-cover { | |
477 | + display: none; /*sorry for IE5*/ | |
478 | + display/**/: block; /*sorry for IE5*/ | |
479 | + position: absolute; /*must have*/ | |
480 | + z-index: -1; /*must have*/ | |
481 | + filter: mask(); /*must have*/ | |
482 | + top: -4px; /*must have*/ | |
483 | + left: -4px; /*must have*/ | |
484 | + width: 200px; /*must have*/ | |
485 | + height: 200px; /*must have*/ | |
486 | +}/* Progressbar | |
487 | +----------------------------------*/ | |
488 | +.ui-progressbar { height:2em; text-align: left; } | |
489 | +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } | |
0 | 490 | \ No newline at end of file | ... | ... |
1.52 KB
public/stylesheets/jquery.ui/sunny/images/ui-bg_diagonals-medium_20_d34d17_40x40.png
0 → 100644
199 Bytes
public/stylesheets/jquery.ui/sunny/images/ui-bg_flat_30_cccccc_40x100.png
0 → 100644
180 Bytes
public/stylesheets/jquery.ui/sunny/images/ui-bg_flat_50_5c5c5c_40x100.png
0 → 100644
180 Bytes
public/stylesheets/jquery.ui/sunny/images/ui-bg_gloss-wave_45_817865_500x100.png
0 → 100644
3.88 KB
public/stylesheets/jquery.ui/sunny/images/ui-bg_gloss-wave_60_fece2f_500x100.png
0 → 100644
3.43 KB
public/stylesheets/jquery.ui/sunny/images/ui-bg_gloss-wave_70_ffdd57_500x100.png
0 → 100644
3.05 KB
public/stylesheets/jquery.ui/sunny/images/ui-bg_gloss-wave_90_fff9e5_500x100.png
0 → 100644
2.2 KB
public/stylesheets/jquery.ui/sunny/images/ui-bg_highlight-soft_100_feeebd_1x100.png
0 → 100644
108 Bytes
public/stylesheets/jquery.ui/sunny/images/ui-bg_inset-soft_30_ffffff_1x100.png
0 → 100644
100 Bytes
4.27 KB
5.23 KB
4.27 KB
4.27 KB
4.27 KB
4.27 KB
5.23 KB
public/stylesheets/jquery.ui/sunny/jquery-ui-1.8.2.custom.css
0 → 100644
... | ... | @@ -0,0 +1,489 @@ |
1 | +/* | |
2 | +* jQuery UI CSS Framework | |
3 | +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) | |
4 | +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
5 | +*/ | |
6 | + | |
7 | +/* Layout helpers | |
8 | +----------------------------------*/ | |
9 | +.ui-helper-hidden { display: none; } | |
10 | +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } | |
11 | +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } | |
12 | +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } | |
13 | +.ui-helper-clearfix { display: inline-block; } | |
14 | +/* required comment for clearfix to work in Opera \*/ | |
15 | +* html .ui-helper-clearfix { height:1%; } | |
16 | +.ui-helper-clearfix { display:block; } | |
17 | +/* end clearfix */ | |
18 | +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } | |
19 | + | |
20 | + | |
21 | +/* Interaction Cues | |
22 | +----------------------------------*/ | |
23 | +.ui-state-disabled { cursor: default !important; } | |
24 | + | |
25 | + | |
26 | +/* Icons | |
27 | +----------------------------------*/ | |
28 | + | |
29 | +/* states and images */ | |
30 | +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } | |
31 | + | |
32 | + | |
33 | +/* Misc visuals | |
34 | +----------------------------------*/ | |
35 | + | |
36 | +/* Overlays */ | |
37 | +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } | |
38 | + | |
39 | + | |
40 | +/* | |
41 | +* jQuery UI CSS Framework | |
42 | +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) | |
43 | +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
44 | +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Segoe%20UI,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=8px&bgColorHeader=817865&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=45&borderColorHeader=494437&fcHeader=ffffff&iconColorHeader=fadc7a&bgColorContent=feeebd&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=8e846b&fcContent=383838&iconColorContent=d19405&bgColorDefault=fece2f&bgTextureDefault=12_gloss_wave.png&bgImgOpacityDefault=60&borderColorDefault=d19405&fcDefault=4c3000&iconColorDefault=3d3d3d&bgColorHover=ffdd57&bgTextureHover=12_gloss_wave.png&bgImgOpacityHover=70&borderColorHover=a45b13&fcHover=381f00&iconColorHover=bd7b00&bgColorActive=ffffff&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=30&borderColorActive=655e4e&fcActive=0074c7&iconColorActive=eb990f&bgColorHighlight=fff9e5&bgTextureHighlight=12_gloss_wave.png&bgImgOpacityHighlight=90&borderColorHighlight=eeb420&fcHighlight=1f1f1f&iconColorHighlight=ed9f26&bgColorError=d34d17&bgTextureError=07_diagonals_medium.png&bgImgOpacityError=20&borderColorError=ffb73d&fcError=ffffff&iconColorError=ffe180&bgColorOverlay=5c5c5c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=01_flat.png&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px | |
45 | +*/ | |
46 | + | |
47 | + | |
48 | +/* Component containers | |
49 | +----------------------------------*/ | |
50 | +.ui-widget { font-family: Segoe UI, Arial, sans-serif; font-size: 1.1em; } | |
51 | +.ui-widget .ui-widget { font-size: 1em; } | |
52 | +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Segoe UI, Arial, sans-serif; font-size: 1em; } | |
53 | +.ui-widget-content { border: 1px solid #8e846b; background: #feeebd url(images/ui-bg_highlight-soft_100_feeebd_1x100.png) 50% top repeat-x; color: #383838; } | |
54 | +.ui-widget-content a { color: #383838; } | |
55 | +.ui-widget-header { border: 1px solid #494437; background: #817865 url(images/ui-bg_gloss-wave_45_817865_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } | |
56 | +.ui-widget-header a { color: #ffffff; } | |
57 | + | |
58 | +/* Interaction states | |
59 | +----------------------------------*/ | |
60 | +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d19405; background: #fece2f url(images/ui-bg_gloss-wave_60_fece2f_500x100.png) 50% 50% repeat-x; font-weight: bold; color: #4c3000; } | |
61 | +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #4c3000; text-decoration: none; } | |
62 | +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #a45b13; background: #ffdd57 url(images/ui-bg_gloss-wave_70_ffdd57_500x100.png) 50% 50% repeat-x; font-weight: bold; color: #381f00; } | |
63 | +.ui-state-hover a, .ui-state-hover a:hover { color: #381f00; text-decoration: none; } | |
64 | +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #655e4e; background: #ffffff url(images/ui-bg_inset-soft_30_ffffff_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #0074c7; } | |
65 | +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #0074c7; text-decoration: none; } | |
66 | +.ui-widget :active { outline: none; } | |
67 | + | |
68 | +/* Interaction Cues | |
69 | +----------------------------------*/ | |
70 | +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #eeb420; background: #fff9e5 url(images/ui-bg_gloss-wave_90_fff9e5_500x100.png) 50% top repeat-x; color: #1f1f1f; } | |
71 | +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #1f1f1f; } | |
72 | +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #ffb73d; background: #d34d17 url(images/ui-bg_diagonals-medium_20_d34d17_40x40.png) 50% 50% repeat; color: #ffffff; } | |
73 | +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } | |
74 | +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } | |
75 | +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } | |
76 | +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } | |
77 | +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } | |
78 | + | |
79 | +/* Icons | |
80 | +----------------------------------*/ | |
81 | + | |
82 | +/* states and images */ | |
83 | +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_d19405_256x240.png); } | |
84 | +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_d19405_256x240.png); } | |
85 | +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_fadc7a_256x240.png); } | |
86 | +.ui-state-default .ui-icon { background-image: url(images/ui-icons_3d3d3d_256x240.png); } | |
87 | +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_bd7b00_256x240.png); } | |
88 | +.ui-state-active .ui-icon {background-image: url(images/ui-icons_eb990f_256x240.png); } | |
89 | +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_ed9f26_256x240.png); } | |
90 | +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffe180_256x240.png); } | |
91 | + | |
92 | +/* positioning */ | |
93 | +.ui-icon-carat-1-n { background-position: 0 0; } | |
94 | +.ui-icon-carat-1-ne { background-position: -16px 0; } | |
95 | +.ui-icon-carat-1-e { background-position: -32px 0; } | |
96 | +.ui-icon-carat-1-se { background-position: -48px 0; } | |
97 | +.ui-icon-carat-1-s { background-position: -64px 0; } | |
98 | +.ui-icon-carat-1-sw { background-position: -80px 0; } | |
99 | +.ui-icon-carat-1-w { background-position: -96px 0; } | |
100 | +.ui-icon-carat-1-nw { background-position: -112px 0; } | |
101 | +.ui-icon-carat-2-n-s { background-position: -128px 0; } | |
102 | +.ui-icon-carat-2-e-w { background-position: -144px 0; } | |
103 | +.ui-icon-triangle-1-n { background-position: 0 -16px; } | |
104 | +.ui-icon-triangle-1-ne { background-position: -16px -16px; } | |
105 | +.ui-icon-triangle-1-e { background-position: -32px -16px; } | |
106 | +.ui-icon-triangle-1-se { background-position: -48px -16px; } | |
107 | +.ui-icon-triangle-1-s { background-position: -64px -16px; } | |
108 | +.ui-icon-triangle-1-sw { background-position: -80px -16px; } | |
109 | +.ui-icon-triangle-1-w { background-position: -96px -16px; } | |
110 | +.ui-icon-triangle-1-nw { background-position: -112px -16px; } | |
111 | +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } | |
112 | +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } | |
113 | +.ui-icon-arrow-1-n { background-position: 0 -32px; } | |
114 | +.ui-icon-arrow-1-ne { background-position: -16px -32px; } | |
115 | +.ui-icon-arrow-1-e { background-position: -32px -32px; } | |
116 | +.ui-icon-arrow-1-se { background-position: -48px -32px; } | |
117 | +.ui-icon-arrow-1-s { background-position: -64px -32px; } | |
118 | +.ui-icon-arrow-1-sw { background-position: -80px -32px; } | |
119 | +.ui-icon-arrow-1-w { background-position: -96px -32px; } | |
120 | +.ui-icon-arrow-1-nw { background-position: -112px -32px; } | |
121 | +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } | |
122 | +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } | |
123 | +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } | |
124 | +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } | |
125 | +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } | |
126 | +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } | |
127 | +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } | |
128 | +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } | |
129 | +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } | |
130 | +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } | |
131 | +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } | |
132 | +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } | |
133 | +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } | |
134 | +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } | |
135 | +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } | |
136 | +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } | |
137 | +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } | |
138 | +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } | |
139 | +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } | |
140 | +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } | |
141 | +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } | |
142 | +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } | |
143 | +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } | |
144 | +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } | |
145 | +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } | |
146 | +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } | |
147 | +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } | |
148 | +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } | |
149 | +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } | |
150 | +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } | |
151 | +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } | |
152 | +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } | |
153 | +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } | |
154 | +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } | |
155 | +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } | |
156 | +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } | |
157 | +.ui-icon-arrow-4 { background-position: 0 -80px; } | |
158 | +.ui-icon-arrow-4-diag { background-position: -16px -80px; } | |
159 | +.ui-icon-extlink { background-position: -32px -80px; } | |
160 | +.ui-icon-newwin { background-position: -48px -80px; } | |
161 | +.ui-icon-refresh { background-position: -64px -80px; } | |
162 | +.ui-icon-shuffle { background-position: -80px -80px; } | |
163 | +.ui-icon-transfer-e-w { background-position: -96px -80px; } | |
164 | +.ui-icon-transferthick-e-w { background-position: -112px -80px; } | |
165 | +.ui-icon-folder-collapsed { background-position: 0 -96px; } | |
166 | +.ui-icon-folder-open { background-position: -16px -96px; } | |
167 | +.ui-icon-document { background-position: -32px -96px; } | |
168 | +.ui-icon-document-b { background-position: -48px -96px; } | |
169 | +.ui-icon-note { background-position: -64px -96px; } | |
170 | +.ui-icon-mail-closed { background-position: -80px -96px; } | |
171 | +.ui-icon-mail-open { background-position: -96px -96px; } | |
172 | +.ui-icon-suitcase { background-position: -112px -96px; } | |
173 | +.ui-icon-comment { background-position: -128px -96px; } | |
174 | +.ui-icon-person { background-position: -144px -96px; } | |
175 | +.ui-icon-print { background-position: -160px -96px; } | |
176 | +.ui-icon-trash { background-position: -176px -96px; } | |
177 | +.ui-icon-locked { background-position: -192px -96px; } | |
178 | +.ui-icon-unlocked { background-position: -208px -96px; } | |
179 | +.ui-icon-bookmark { background-position: -224px -96px; } | |
180 | +.ui-icon-tag { background-position: -240px -96px; } | |
181 | +.ui-icon-home { background-position: 0 -112px; } | |
182 | +.ui-icon-flag { background-position: -16px -112px; } | |
183 | +.ui-icon-calendar { background-position: -32px -112px; } | |
184 | +.ui-icon-cart { background-position: -48px -112px; } | |
185 | +.ui-icon-pencil { background-position: -64px -112px; } | |
186 | +.ui-icon-clock { background-position: -80px -112px; } | |
187 | +.ui-icon-disk { background-position: -96px -112px; } | |
188 | +.ui-icon-calculator { background-position: -112px -112px; } | |
189 | +.ui-icon-zoomin { background-position: -128px -112px; } | |
190 | +.ui-icon-zoomout { background-position: -144px -112px; } | |
191 | +.ui-icon-search { background-position: -160px -112px; } | |
192 | +.ui-icon-wrench { background-position: -176px -112px; } | |
193 | +.ui-icon-gear { background-position: -192px -112px; } | |
194 | +.ui-icon-heart { background-position: -208px -112px; } | |
195 | +.ui-icon-star { background-position: -224px -112px; } | |
196 | +.ui-icon-link { background-position: -240px -112px; } | |
197 | +.ui-icon-cancel { background-position: 0 -128px; } | |
198 | +.ui-icon-plus { background-position: -16px -128px; } | |
199 | +.ui-icon-plusthick { background-position: -32px -128px; } | |
200 | +.ui-icon-minus { background-position: -48px -128px; } | |
201 | +.ui-icon-minusthick { background-position: -64px -128px; } | |
202 | +.ui-icon-close { background-position: -80px -128px; } | |
203 | +.ui-icon-closethick { background-position: -96px -128px; } | |
204 | +.ui-icon-key { background-position: -112px -128px; } | |
205 | +.ui-icon-lightbulb { background-position: -128px -128px; } | |
206 | +.ui-icon-scissors { background-position: -144px -128px; } | |
207 | +.ui-icon-clipboard { background-position: -160px -128px; } | |
208 | +.ui-icon-copy { background-position: -176px -128px; } | |
209 | +.ui-icon-contact { background-position: -192px -128px; } | |
210 | +.ui-icon-image { background-position: -208px -128px; } | |
211 | +.ui-icon-video { background-position: -224px -128px; } | |
212 | +.ui-icon-script { background-position: -240px -128px; } | |
213 | +.ui-icon-alert { background-position: 0 -144px; } | |
214 | +.ui-icon-info { background-position: -16px -144px; } | |
215 | +.ui-icon-notice { background-position: -32px -144px; } | |
216 | +.ui-icon-help { background-position: -48px -144px; } | |
217 | +.ui-icon-check { background-position: -64px -144px; } | |
218 | +.ui-icon-bullet { background-position: -80px -144px; } | |
219 | +.ui-icon-radio-off { background-position: -96px -144px; } | |
220 | +.ui-icon-radio-on { background-position: -112px -144px; } | |
221 | +.ui-icon-pin-w { background-position: -128px -144px; } | |
222 | +.ui-icon-pin-s { background-position: -144px -144px; } | |
223 | +.ui-icon-play { background-position: 0 -160px; } | |
224 | +.ui-icon-pause { background-position: -16px -160px; } | |
225 | +.ui-icon-seek-next { background-position: -32px -160px; } | |
226 | +.ui-icon-seek-prev { background-position: -48px -160px; } | |
227 | +.ui-icon-seek-end { background-position: -64px -160px; } | |
228 | +.ui-icon-seek-start { background-position: -80px -160px; } | |
229 | +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ | |
230 | +.ui-icon-seek-first { background-position: -80px -160px; } | |
231 | +.ui-icon-stop { background-position: -96px -160px; } | |
232 | +.ui-icon-eject { background-position: -112px -160px; } | |
233 | +.ui-icon-volume-off { background-position: -128px -160px; } | |
234 | +.ui-icon-volume-on { background-position: -144px -160px; } | |
235 | +.ui-icon-power { background-position: 0 -176px; } | |
236 | +.ui-icon-signal-diag { background-position: -16px -176px; } | |
237 | +.ui-icon-signal { background-position: -32px -176px; } | |
238 | +.ui-icon-battery-0 { background-position: -48px -176px; } | |
239 | +.ui-icon-battery-1 { background-position: -64px -176px; } | |
240 | +.ui-icon-battery-2 { background-position: -80px -176px; } | |
241 | +.ui-icon-battery-3 { background-position: -96px -176px; } | |
242 | +.ui-icon-circle-plus { background-position: 0 -192px; } | |
243 | +.ui-icon-circle-minus { background-position: -16px -192px; } | |
244 | +.ui-icon-circle-close { background-position: -32px -192px; } | |
245 | +.ui-icon-circle-triangle-e { background-position: -48px -192px; } | |
246 | +.ui-icon-circle-triangle-s { background-position: -64px -192px; } | |
247 | +.ui-icon-circle-triangle-w { background-position: -80px -192px; } | |
248 | +.ui-icon-circle-triangle-n { background-position: -96px -192px; } | |
249 | +.ui-icon-circle-arrow-e { background-position: -112px -192px; } | |
250 | +.ui-icon-circle-arrow-s { background-position: -128px -192px; } | |
251 | +.ui-icon-circle-arrow-w { background-position: -144px -192px; } | |
252 | +.ui-icon-circle-arrow-n { background-position: -160px -192px; } | |
253 | +.ui-icon-circle-zoomin { background-position: -176px -192px; } | |
254 | +.ui-icon-circle-zoomout { background-position: -192px -192px; } | |
255 | +.ui-icon-circle-check { background-position: -208px -192px; } | |
256 | +.ui-icon-circlesmall-plus { background-position: 0 -208px; } | |
257 | +.ui-icon-circlesmall-minus { background-position: -16px -208px; } | |
258 | +.ui-icon-circlesmall-close { background-position: -32px -208px; } | |
259 | +.ui-icon-squaresmall-plus { background-position: -48px -208px; } | |
260 | +.ui-icon-squaresmall-minus { background-position: -64px -208px; } | |
261 | +.ui-icon-squaresmall-close { background-position: -80px -208px; } | |
262 | +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } | |
263 | +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } | |
264 | +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } | |
265 | +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } | |
266 | +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } | |
267 | +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } | |
268 | + | |
269 | + | |
270 | +/* Misc visuals | |
271 | +----------------------------------*/ | |
272 | + | |
273 | +/* Corner radius */ | |
274 | +.ui-corner-tl { -moz-border-radius-topleft: 8px; -webkit-border-top-left-radius: 8px; border-top-left-radius: 8px; } | |
275 | +.ui-corner-tr { -moz-border-radius-topright: 8px; -webkit-border-top-right-radius: 8px; border-top-right-radius: 8px; } | |
276 | +.ui-corner-bl { -moz-border-radius-bottomleft: 8px; -webkit-border-bottom-left-radius: 8px; border-bottom-left-radius: 8px; } | |
277 | +.ui-corner-br { -moz-border-radius-bottomright: 8px; -webkit-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; } | |
278 | +.ui-corner-top { -moz-border-radius-topleft: 8px; -webkit-border-top-left-radius: 8px; border-top-left-radius: 8px; -moz-border-radius-topright: 8px; -webkit-border-top-right-radius: 8px; border-top-right-radius: 8px; } | |
279 | +.ui-corner-bottom { -moz-border-radius-bottomleft: 8px; -webkit-border-bottom-left-radius: 8px; border-bottom-left-radius: 8px; -moz-border-radius-bottomright: 8px; -webkit-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; } | |
280 | +.ui-corner-right { -moz-border-radius-topright: 8px; -webkit-border-top-right-radius: 8px; border-top-right-radius: 8px; -moz-border-radius-bottomright: 8px; -webkit-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; } | |
281 | +.ui-corner-left { -moz-border-radius-topleft: 8px; -webkit-border-top-left-radius: 8px; border-top-left-radius: 8px; -moz-border-radius-bottomleft: 8px; -webkit-border-bottom-left-radius: 8px; border-bottom-left-radius: 8px; } | |
282 | +.ui-corner-all { -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; } | |
283 | + | |
284 | +/* Overlays */ | |
285 | +.ui-widget-overlay { background: #5c5c5c url(images/ui-bg_flat_50_5c5c5c_40x100.png) 50% 50% repeat-x; opacity: .80;filter:Alpha(Opacity=80); } | |
286 | +.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; background: #cccccc url(images/ui-bg_flat_30_cccccc_40x100.png) 50% 50% repeat-x; opacity: .60;filter:Alpha(Opacity=60); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Resizable | |
287 | +----------------------------------*/ | |
288 | +.ui-resizable { position: relative;} | |
289 | +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} | |
290 | +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } | |
291 | +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } | |
292 | +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } | |
293 | +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } | |
294 | +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } | |
295 | +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } | |
296 | +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } | |
297 | +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } | |
298 | +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable | |
299 | +----------------------------------*/ | |
300 | +.ui-selectable-helper { border:1px dotted black } | |
301 | +/* Accordion | |
302 | +----------------------------------*/ | |
303 | +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } | |
304 | +.ui-accordion .ui-accordion-li-fix { display: inline; } | |
305 | +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } | |
306 | +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } | |
307 | +/* IE7-/Win - Fix extra vertical space in lists */ | |
308 | +.ui-accordion a { zoom: 1; } | |
309 | +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } | |
310 | +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } | |
311 | +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } | |
312 | +.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete | |
313 | +----------------------------------*/ | |
314 | +.ui-autocomplete { position: absolute; cursor: default; } | |
315 | +.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; } | |
316 | + | |
317 | +/* workarounds */ | |
318 | +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ | |
319 | + | |
320 | +/* Menu | |
321 | +----------------------------------*/ | |
322 | +.ui-menu { | |
323 | + list-style:none; | |
324 | + padding: 2px; | |
325 | + margin: 0; | |
326 | + display:block; | |
327 | +} | |
328 | +.ui-menu .ui-menu { | |
329 | + margin-top: -3px; | |
330 | +} | |
331 | +.ui-menu .ui-menu-item { | |
332 | + margin:0; | |
333 | + padding: 0; | |
334 | + zoom: 1; | |
335 | + float: left; | |
336 | + clear: left; | |
337 | + width: 100%; | |
338 | +} | |
339 | +.ui-menu .ui-menu-item a { | |
340 | + text-decoration:none; | |
341 | + display:block; | |
342 | + padding:.2em .4em; | |
343 | + line-height:1.5; | |
344 | + zoom:1; | |
345 | +} | |
346 | +.ui-menu .ui-menu-item a.ui-state-hover, | |
347 | +.ui-menu .ui-menu-item a.ui-state-active { | |
348 | + font-weight: normal; | |
349 | + margin: -1px; | |
350 | +} | |
351 | +/* Button | |
352 | +----------------------------------*/ | |
353 | + | |
354 | +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ | |
355 | +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ | |
356 | +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ | |
357 | +.ui-button-icons-only { width: 3.4em; } | |
358 | +button.ui-button-icons-only { width: 3.7em; } | |
359 | + | |
360 | +/*button text element */ | |
361 | +.ui-button .ui-button-text { display: block; line-height: 1.4; } | |
362 | +.ui-button-text-only .ui-button-text { padding: .4em 1em; } | |
363 | +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } | |
364 | +.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } | |
365 | +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } | |
366 | +/* no icon support for input elements, provide padding by default */ | |
367 | +input.ui-button { padding: .4em 1em; } | |
368 | + | |
369 | +/*button icon element(s) */ | |
370 | +.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } | |
371 | +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } | |
372 | +.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } | |
373 | +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } | |
374 | + | |
375 | +/*button sets*/ | |
376 | +.ui-buttonset { margin-right: 7px; } | |
377 | +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } | |
378 | + | |
379 | +/* workarounds */ | |
380 | +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ | |
381 | + | |
382 | + | |
383 | + | |
384 | + | |
385 | + | |
386 | +/* Dialog | |
387 | +----------------------------------*/ | |
388 | +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } | |
389 | +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } | |
390 | +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } | |
391 | +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } | |
392 | +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } | |
393 | +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } | |
394 | +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } | |
395 | +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } | |
396 | +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } | |
397 | +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } | |
398 | +.ui-draggable .ui-dialog-titlebar { cursor: move; } | |
399 | +/* Slider | |
400 | +----------------------------------*/ | |
401 | +.ui-slider { position: relative; text-align: left; } | |
402 | +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } | |
403 | +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } | |
404 | + | |
405 | +.ui-slider-horizontal { height: .8em; } | |
406 | +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } | |
407 | +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } | |
408 | +.ui-slider-horizontal .ui-slider-range-min { left: 0; } | |
409 | +.ui-slider-horizontal .ui-slider-range-max { right: 0; } | |
410 | + | |
411 | +.ui-slider-vertical { width: .8em; height: 100px; } | |
412 | +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } | |
413 | +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } | |
414 | +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } | |
415 | +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs | |
416 | +----------------------------------*/ | |
417 | +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ | |
418 | +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } | |
419 | +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } | |
420 | +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } | |
421 | +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } | |
422 | +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } | |
423 | +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ | |
424 | +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } | |
425 | +.ui-tabs .ui-tabs-hide { display: none !important; } | |
426 | +/* Datepicker | |
427 | +----------------------------------*/ | |
428 | +.ui-datepicker { width: 17em; padding: .2em .2em 0; } | |
429 | +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } | |
430 | +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } | |
431 | +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } | |
432 | +.ui-datepicker .ui-datepicker-prev { left:2px; } | |
433 | +.ui-datepicker .ui-datepicker-next { right:2px; } | |
434 | +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } | |
435 | +.ui-datepicker .ui-datepicker-next-hover { right:1px; } | |
436 | +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } | |
437 | +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } | |
438 | +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } | |
439 | +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} | |
440 | +.ui-datepicker select.ui-datepicker-month, | |
441 | +.ui-datepicker select.ui-datepicker-year { width: 49%;} | |
442 | +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } | |
443 | +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } | |
444 | +.ui-datepicker td { border: 0; padding: 1px; } | |
445 | +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } | |
446 | +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } | |
447 | +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } | |
448 | +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } | |
449 | + | |
450 | +/* with multiple calendars */ | |
451 | +.ui-datepicker.ui-datepicker-multi { width:auto; } | |
452 | +.ui-datepicker-multi .ui-datepicker-group { float:left; } | |
453 | +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } | |
454 | +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } | |
455 | +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } | |
456 | +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } | |
457 | +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } | |
458 | +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } | |
459 | +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } | |
460 | +.ui-datepicker-row-break { clear:both; width:100%; } | |
461 | + | |
462 | +/* RTL support */ | |
463 | +.ui-datepicker-rtl { direction: rtl; } | |
464 | +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } | |
465 | +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } | |
466 | +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } | |
467 | +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } | |
468 | +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } | |
469 | +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } | |
470 | +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } | |
471 | +.ui-datepicker-rtl .ui-datepicker-group { float:right; } | |
472 | +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } | |
473 | +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } | |
474 | + | |
475 | +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ | |
476 | +.ui-datepicker-cover { | |
477 | + display: none; /*sorry for IE5*/ | |
478 | + display/**/: block; /*sorry for IE5*/ | |
479 | + position: absolute; /*must have*/ | |
480 | + z-index: -1; /*must have*/ | |
481 | + filter: mask(); /*must have*/ | |
482 | + top: -4px; /*must have*/ | |
483 | + left: -4px; /*must have*/ | |
484 | + width: 200px; /*must have*/ | |
485 | + height: 200px; /*must have*/ | |
486 | +}/* Progressbar | |
487 | +----------------------------------*/ | |
488 | +.ui-progressbar { height:2em; text-align: left; } | |
489 | +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } | |
0 | 490 | \ No newline at end of file | ... | ... |
test/functional/catalog_controller_test.rb
... | ... | @@ -39,31 +39,6 @@ class CatalogControllerTest < Test::Unit::TestCase |
39 | 39 | assert_kind_of Array, assigns(:products) |
40 | 40 | end |
41 | 41 | |
42 | - should 'show product of enterprise' do | |
43 | - prod = @enterprise.products.create!(:name => 'Product test', :product_category => @product_category) | |
44 | - get :show, :id => prod.id, :profile => @enterprise.identifier | |
45 | - assert_tag :tag => 'h1', :content => /#{prod.name}/ | |
46 | - end | |
47 | - | |
48 | - should 'link back to index from product show' do | |
49 | - enterprise = Enterprise.create!(:name => 'test_enterprise_1', :identifier => 'test_enterprise_1', :environment => Environment.default) | |
50 | - prod = enterprise.products.create!(:name => 'Product test', :product_category => @product_category) | |
51 | - get :show, :id => prod.id, :profile => enterprise.identifier | |
52 | - assert_tag({ | |
53 | - :tag => 'div', | |
54 | - :attributes => { | |
55 | - :class => /main-block/ | |
56 | - }, | |
57 | - :descendant => { | |
58 | - :tag => 'a', | |
59 | - :attributes => { | |
60 | - :href => "/catalog/#{enterprise.identifier}" | |
61 | - } | |
62 | - } | |
63 | - }) | |
64 | - | |
65 | - end | |
66 | - | |
67 | 42 | should 'not give access if environment do not let' do |
68 | 43 | env = Environment.default |
69 | 44 | env.enable('disable_products_for_enterprises') |
... | ... | @@ -86,20 +61,6 @@ class CatalogControllerTest < Test::Unit::TestCase |
86 | 61 | assert_tag :tag => 'li', :attributes => { :class => 'product_price' }, :content => /Price:/ |
87 | 62 | end |
88 | 63 | |
89 | - should 'not show product price when showing product if not informed' do | |
90 | - prod = @enterprise.products.create!(:name => 'Product test', :product_category => @product_category) | |
91 | - get :show, :id => prod.id, :profile => @enterprise.identifier | |
92 | - | |
93 | - assert_no_tag :tag => 'p', :attributes => { :class => 'product_price' }, :content => /Price:/ | |
94 | - end | |
95 | - | |
96 | - should 'show product price when showing product if informed' do | |
97 | - prod = @enterprise.products.create!(:name => 'Product test', :price => 50.00, :product_category => @product_category) | |
98 | - get :show, :id => prod.id, :profile => @enterprise.identifier | |
99 | - | |
100 | - assert_tag :tag => 'p', :attributes => { :class => 'product_price' }, :content => /Price:/ | |
101 | - end | |
102 | - | |
103 | 64 | should 'link to assets products wiht product category in the link to product category on index' do |
104 | 65 | pc = ProductCategory.create!(:name => 'some product', :environment => enterprise.environment) |
105 | 66 | prod = enterprise.products.create!(:name => 'Product test', :price => 50.00, :product_category => pc) |
... | ... | @@ -108,12 +69,4 @@ class CatalogControllerTest < Test::Unit::TestCase |
108 | 69 | assert_tag :tag => 'a', :attributes => {:href => /assets\/products\?product_category=#{pc.id}/} |
109 | 70 | end |
110 | 71 | |
111 | - should 'link to assets products wiht product category in the link to product category on show' do | |
112 | - pc = ProductCategory.create!(:name => 'some product', :environment => enterprise.environment) | |
113 | - prod = enterprise.products.create!(:name => 'Product test', :price => 50.00, :product_category => pc) | |
114 | - | |
115 | - get :show, :id => prod.id, :profile => enterprise.identifier | |
116 | - assert_tag :tag => 'a', :attributes => {:href => /assets\/products\?product_category=#{pc.id}/} | |
117 | - end | |
118 | - | |
119 | 72 | end | ... | ... |
test/functional/manage_products_controller_test.rb
... | ... | @@ -65,27 +65,60 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
65 | 65 | end |
66 | 66 | end |
67 | 67 | |
68 | - should "get edit form" do | |
69 | - p = @enterprise.products.create!(:name => 'test product', :product_category => @product_category) | |
70 | - get 'edit', :profile => @enterprise.identifier, :id => p.id | |
68 | + should "get edit name form" do | |
69 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
70 | + get 'edit', :profile => @enterprise.identifier, :id => product.id, :field => 'name' | |
71 | 71 | assert_response :success |
72 | 72 | assert assigns(:product) |
73 | - assert_template 'edit' | |
74 | - assert_tag :tag => 'form', :attributes => { :action => /edit/ } | |
73 | + assert_tag :tag => 'form', :attributes => { :action => /myprofile\/#{@enterprise.identifier}\/manage_products\/edit\/#{product.id}\?field=name/ } | |
75 | 74 | end |
76 | 75 | |
77 | - should "edit product" do | |
78 | - p = @enterprise.products.create!(:name => 'test product', :product_category => @product_category) | |
79 | - post 'edit', :profile => @enterprise.identifier, :product => {:name => 'new test product'}, :id => p.id | |
80 | - assert_response :redirect | |
76 | + should "get edit info form" do | |
77 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
78 | + get 'edit', :profile => @enterprise.identifier, :id => product.id, :field => 'info' | |
79 | + assert_response :success | |
80 | + assert assigns(:product) | |
81 | + assert_tag :tag => 'form', :attributes => { :action => /myprofile\/#{@enterprise.identifier}\/manage_products\/edit\/#{product.id}\?field=info/ } | |
82 | + end | |
83 | + | |
84 | + should "get edit image form" do | |
85 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
86 | + get 'edit', :profile => @enterprise.identifier, :id => product.id, :field => 'image' | |
87 | + assert_response :success | |
88 | + assert assigns(:product) | |
89 | + assert_tag :tag => 'form', :attributes => { :action => /myprofile\/#{@enterprise.identifier}\/manage_products\/edit\/#{product.id}\?field=image/ } | |
90 | + end | |
91 | + | |
92 | + should "edit product name" do | |
93 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
94 | + post :edit, :profile => @enterprise.identifier, :product => {:name => 'new test product'}, :id => product.id, :field => 'name' | |
95 | + assert_response :success | |
81 | 96 | assert assigns(:product) |
82 | 97 | assert ! assigns(:product).new_record? |
83 | - assert_equal p, Product.find_by_name('new test product') | |
98 | + assert_equal product, Product.find_by_name('new test product') | |
99 | + end | |
100 | + | |
101 | + should "edit product description" do | |
102 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id, :description => 'My product is very good') | |
103 | + post :edit, :profile => @enterprise.identifier, :product => {:description => 'A very good product!'}, :id => product.id, :field => 'info' | |
104 | + assert_response :success | |
105 | + assert assigns(:product) | |
106 | + assert ! assigns(:product).new_record? | |
107 | + assert_equal 'A very good product!', Product.find_by_name('test product').description | |
108 | + end | |
109 | + | |
110 | + should "edit product image" do | |
111 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
112 | + post :edit, :profile => @enterprise.identifier, :product => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }, :id => product.id, :field => 'image' | |
113 | + assert_response :success | |
114 | + assert assigns(:product) | |
115 | + assert ! assigns(:product).new_record? | |
116 | + assert_equal 'rails.png', Product.find_by_name('test product').image.filename | |
84 | 117 | end |
85 | 118 | |
86 | 119 | should "not edit to invalid parameters" do |
87 | - p = @enterprise.products.create!(:name => 'test product', :product_category => @product_category) | |
88 | - post 'edit', :profile => @enterprise.identifier, :product => {:product_category => nil}, :id => p.id | |
120 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
121 | + post 'edit_category', :profile => @enterprise.identifier, :product => {:product_category => nil}, :id => product.id | |
89 | 122 | assert_response :success |
90 | 123 | assert assigns(:product) |
91 | 124 | assert ! assigns(:product).valid? |
... | ... | @@ -131,32 +164,16 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
131 | 164 | end |
132 | 165 | end |
133 | 166 | |
134 | - should 'show thumbnail image when edit product' do | |
135 | - p = @enterprise.products.create!(:name => 'test product1', :product_category => @product_category, :image_builder => { | |
136 | - :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | |
137 | - }) | |
138 | - get 'edit', :profile => @enterprise.identifier, :id => p.id | |
139 | - assert_tag :tag => 'img', :attributes => { :src => /#{p.image.public_filename(:thumb)}/ } | |
140 | - end | |
141 | - | |
142 | - should 'show change image link above thumbnail image' do | |
143 | - p = @enterprise.products.create!(:name => 'test product1', :product_category => @product_category, :image_builder => { | |
144 | - :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') | |
145 | - }) | |
146 | - get 'edit', :profile => @enterprise.identifier, :id => p.id | |
147 | - assert_tag :tag => 'a', :attributes => { :href => '#' }, :content => 'Change image' | |
148 | - end | |
149 | - | |
150 | 167 | should 'filter html from name of product' do |
151 | 168 | category = fast_create(ProductCategory, :name => 'Category 1') |
152 | 169 | post 'new', :profile => @enterprise.identifier, :product => { :name => "<b id='html_name'>name bold</b>", :product_category_id => category.id } |
153 | 170 | assert_sanitized assigns(:product).name |
154 | 171 | end |
155 | 172 | |
156 | - should 'filter html from description of product' do | |
173 | + should 'filter html with whit list from description of product' do | |
157 | 174 | category = fast_create(ProductCategory, :name => 'Category 1') |
158 | 175 | post 'new', :profile => @enterprise.identifier, :product => { :name => 'name', :description => "<b id='html_descr'>descr bold</b>", :product_category_id => category.id } |
159 | - assert_sanitized assigns(:product).description | |
176 | + assert_equal "<b>descr bold</b>", assigns(:product).description | |
160 | 177 | end |
161 | 178 | |
162 | 179 | should 'not let users in if environment do not let' do |
... | ... | @@ -179,15 +196,6 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
179 | 196 | assert_equivalent ProductCategory.top_level_for(pc1.environment), assigns(:categories) |
180 | 197 | end |
181 | 198 | |
182 | - should 'links to products asset for product category link when showing' do | |
183 | - pc = fast_create(ProductCategory, :name => 'test_category') | |
184 | - p = @enterprise.products.create!(:name => 'test product', :product_category => pc) | |
185 | - | |
186 | - get :show, :profile => @enterprise.identifier, :id => p.id | |
187 | - | |
188 | - assert_tag :tag => 'a', :attributes => {:href => /assets\/products\?product_category=#{pc.id}/} | |
189 | - end | |
190 | - | |
191 | 199 | should 'increase level while navigate on hierarchy categories' do |
192 | 200 | category_level0 = fast_create(ProductCategory, :name => 'Products', :environment_id => @environment.id) |
193 | 201 | category_level1 = fast_create(ProductCategory, :parent_id => category_level0.id, :name => 'Shoes', :environment_id => @environment.id) |
... | ... | @@ -232,4 +240,58 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
232 | 240 | end |
233 | 241 | end |
234 | 242 | |
243 | + should 'show product of enterprise' do | |
244 | + prod = @enterprise.products.create!(:name => 'Product test', :product_category => @product_category) | |
245 | + get :show, :id => prod.id, :profile => @enterprise.identifier | |
246 | + assert_tag :tag => 'h2', :content => /#{prod.name}/ | |
247 | + end | |
248 | + | |
249 | + should 'link back to index from product show' do | |
250 | + enterprise = Enterprise.create!(:name => 'test_enterprise_1', :identifier => 'test_enterprise_1', :environment => Environment.default) | |
251 | + prod = enterprise.products.create!(:name => 'Product test', :product_category => @product_category) | |
252 | + get :show, :id => prod.id, :profile => enterprise.identifier | |
253 | + assert_tag({ | |
254 | + :tag => 'div', | |
255 | + :attributes => { | |
256 | + :class => /main-block/ | |
257 | + }, | |
258 | + :descendant => { | |
259 | + :tag => 'a', | |
260 | + :attributes => { | |
261 | + :href => "/myprofile/#{enterprise.identifier}/manage_products", | |
262 | + }, | |
263 | + :content => /Back to the product listing/ | |
264 | + } | |
265 | + }) | |
266 | + end | |
267 | + | |
268 | + should 'not show product price when showing product if not informed' do | |
269 | + product = fast_create(Product, :name => 'test product', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
270 | + get :show, :id => product.id, :profile => @enterprise.identifier | |
271 | + | |
272 | + assert_no_tag :tag => 'span', :attributes => { :class => 'product_price' }, :content => /Price:/ | |
273 | + end | |
274 | + | |
275 | + should 'show product price when showing product if unit was informed' do | |
276 | + prod = @enterprise.products.create!(:name => 'Product test', :price => 50.00, :unit => 'unit', :product_category => @product_category) | |
277 | + get :show, :id => prod.id, :profile => @enterprise.identifier | |
278 | + | |
279 | + assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /Price:/ | |
280 | + end | |
281 | + | |
282 | + should 'show product price when showing product if discount was informed' do | |
283 | + prod = @enterprise.products.create!(:name => 'Product test', :price => 50.00, :discount => 3.50, :unit => 'unit', :product_category => @product_category) | |
284 | + get :show, :id => prod.id, :profile => @enterprise.identifier | |
285 | + | |
286 | + assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /List price:/ | |
287 | + assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /On sale:/ | |
288 | + end | |
289 | + | |
290 | + should 'not show product price when showing product if unit not informed' do | |
291 | + prod = @enterprise.products.create!(:name => 'Product test', :price => 50.00, :product_category => @product_category) | |
292 | + get :show, :id => prod.id, :profile => @enterprise.identifier | |
293 | + | |
294 | + assert_no_tag :tag => 'span', :attributes => { :class => 'product_price' }, :content => /Price:/ | |
295 | + end | |
296 | + | |
235 | 297 | end | ... | ... |
test/integration/routing_test.rb
... | ... | @@ -160,12 +160,6 @@ class RoutingTest < ActionController::IntegrationTest |
160 | 160 | |
161 | 161 | def test_catalog_routing |
162 | 162 | assert_routing('/catalog/colivre', :controller => 'catalog', :action => 'index', :profile => 'colivre') |
163 | - assert_routing('/catalog/colivre/1234', :controller => 'catalog', :action => 'show', :profile => 'colivre', :id => '1234') | |
164 | - end | |
165 | - | |
166 | - def test_catalog_with_dot_routing | |
167 | - assert_routing('/catalog/profile.withdot', :controller => 'catalog', :action => 'index', :profile => 'profile.withdot') | |
168 | - assert_routing('/catalog/profile.withdot/1234', :controller => 'catalog', :action => 'show', :profile => 'profile.withdot', :id => '1234') | |
169 | 163 | end |
170 | 164 | |
171 | 165 | def test_hosted_domain_routing | ... | ... |
test/unit/application_helper_test.rb
... | ... | @@ -579,11 +579,6 @@ class ApplicationHelperTest < Test::Unit::TestCase |
579 | 579 | assert_equal 'filename.mp3', short_filename('filename.mp3') |
580 | 580 | end |
581 | 581 | |
582 | - include ActionView::Helpers::NumberHelper | |
583 | - should 'format float to money as Brazillian currency' do | |
584 | - assert_equal 'R$10,00', float_to_currency(10.0) | |
585 | - end | |
586 | - | |
587 | 582 | protected |
588 | 583 | |
589 | 584 | def url_for(args = {}) | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +require File.dirname(__FILE__) + '/../test_helper' | |
2 | + | |
3 | +class CertifierTest < Test::Unit::TestCase | |
4 | + | |
5 | + should 'have link' do | |
6 | + certifier = Certifier.new | |
7 | + | |
8 | + assert_equal '', certifier.link | |
9 | + | |
10 | + certifier.link = 'http://noosfero.org' | |
11 | + assert_equal 'http://noosfero.org', certifier.link | |
12 | + end | |
13 | + | |
14 | +end | ... | ... |
test/unit/enterprise_homepage_test.rb
... | ... | @@ -52,7 +52,7 @@ class EnterpriseHomepageTest < Test::Unit::TestCase |
52 | 52 | a = EnterpriseHomepage.new(:name => 'article homepage') |
53 | 53 | ent.articles << a |
54 | 54 | result = a.to_html |
55 | - assert_match /catalog\/test_enterprise\/#{prod.id}/, result | |
55 | + assert_match /\/test_enterprise\/manage_products\/show\/#{prod.id}/, result | |
56 | 56 | end |
57 | 57 | |
58 | 58 | should 'can display hits' do | ... | ... |
test/unit/environment_test.rb
... | ... | @@ -948,4 +948,28 @@ class EnvironmentTest < Test::Unit::TestCase |
948 | 948 | assert !v.has_terms_of_use? |
949 | 949 | end |
950 | 950 | |
951 | + should 'have currency unit attribute' do | |
952 | + env = Environment.new | |
953 | + assert_equal env.currency_unit, '$' | |
954 | + | |
955 | + env.currency_unit = 'R$' | |
956 | + assert_equal 'R$', env.currency_unit | |
957 | + end | |
958 | + | |
959 | + should 'have currency separator attribute' do | |
960 | + env = Environment.new | |
961 | + assert_equal env.currency_separator, '.' | |
962 | + | |
963 | + env.currency_separator = ',' | |
964 | + assert_equal ',', env.currency_separator | |
965 | + end | |
966 | + | |
967 | + should 'have currency delimiter attribute' do | |
968 | + env = Environment.new | |
969 | + assert_equal env.currency_delimiter, ',' | |
970 | + | |
971 | + env.currency_delimiter = '.' | |
972 | + assert_equal '.', env.currency_delimiter | |
973 | + end | |
974 | + | |
951 | 975 | end | ... | ... |
test/unit/manage_products_helper_test.rb
... | ... | @@ -38,6 +38,63 @@ class ManageProductsHelperTest < Test::Unit::TestCase |
38 | 38 | assert_tag_in_string select_for_categories(category_1.children(true), 1), :tag => 'select', :attributes => {:id => 'category_id'} |
39 | 39 | end |
40 | 40 | |
41 | + include ActionView::Helpers::NumberHelper | |
42 | + should 'format price to environment currency' do | |
43 | + @environment.currency_unit = "R$" | |
44 | + @environment.currency_separator = "," | |
45 | + @environment.currency_delimiter = "." | |
46 | + @environment.save | |
47 | + assert_equal 'R$ 10,00', float_to_currency(10.0) | |
48 | + end | |
49 | + | |
50 | + should 'not display link to edit product when user does not have permission' do | |
51 | + user = mock | |
52 | + user.expects(:has_permission?).with(anything, anything).returns(false) | |
53 | + @controller = mock | |
54 | + @controller.expects(:user).returns(user).at_least_once | |
55 | + @controller.expects(:profile).returns(mock) | |
56 | + category = fast_create(ProductCategory, :name => 'Category 1', :environment_id => @environment.id) | |
57 | + product = fast_create(Product, :product_category_id => category.id) | |
58 | + assert_equal '', edit_product_link(product, 'field', 'link to edit') | |
59 | + end | |
60 | + | |
61 | + should 'display link to edit product when user has permission' do | |
62 | + user = mock | |
63 | + user.expects(:has_permission?).with(anything, anything).returns(true) | |
64 | + @controller = mock | |
65 | + @controller.expects(:user).returns(user).at_least_once | |
66 | + @controller.expects(:profile).returns(mock) | |
67 | + category = fast_create(ProductCategory, :name => 'Category 1', :environment_id => @environment.id) | |
68 | + product = fast_create(Product, :product_category_id => category.id) | |
69 | + | |
70 | + expects(:link_to_remote).with('link to edit', {:update => "product-name", :url => {:controller => 'manage_products', :action => 'edit', :id => product.id, :field => 'name'}, :method => :get}, anything).returns('LINK') | |
71 | + | |
72 | + assert_equal 'LINK', edit_product_link(product, 'name', 'link to edit') | |
73 | + end | |
74 | + | |
75 | + should 'not display link to edit product category when user does not have permission' do | |
76 | + user = mock | |
77 | + user.expects(:has_permission?).with(anything, anything).returns(false) | |
78 | + @controller = mock | |
79 | + @controller.expects(:user).returns(user).at_least_once | |
80 | + @controller.expects(:profile).returns(mock) | |
81 | + category = fast_create(ProductCategory, :name => 'Category 1', :environment_id => @environment.id) | |
82 | + product = fast_create(Product, :product_category_id => category.id) | |
83 | + assert_equal '', edit_product_category_link(product) | |
84 | + end | |
85 | + | |
86 | + should 'display link to edit product category when user has permission' do | |
87 | + user = mock | |
88 | + user.expects(:has_permission?).with(anything, anything).returns(true) | |
89 | + @controller = mock | |
90 | + @controller.expects(:user).returns(user).at_least_once | |
91 | + @controller.expects(:profile).returns(mock) | |
92 | + category = fast_create(ProductCategory, :name => 'Category 1', :environment_id => @environment.id) | |
93 | + product = fast_create(Product, :product_category_id => category.id) | |
94 | + | |
95 | + assert_tag_in_string edit_product_category_link(product), {:tag => 'a', :content => 'Change category'} | |
96 | + end | |
97 | + | |
41 | 98 | protected |
42 | 99 | include NoosferoTestHelper |
43 | 100 | ... | ... |
test/unit/product_test.rb
... | ... | @@ -20,6 +20,27 @@ class ProductTest < Test::Unit::TestCase |
20 | 20 | end |
21 | 21 | end |
22 | 22 | |
23 | + should 'display category name if name is nil' do | |
24 | + p = fast_create(Product, :name => nil) | |
25 | + p.expects(:category_name).returns('Software') | |
26 | + assert_equal 'Software', p.name | |
27 | + end | |
28 | + | |
29 | + should 'display category name if name is blank' do | |
30 | + p = fast_create(Product, :name => '') | |
31 | + p.expects(:category_name).returns('Software') | |
32 | + assert_equal 'Software', p.name | |
33 | + end | |
34 | + | |
35 | + should 'set nil to name if name is equal to category name' do | |
36 | + p = fast_create(Product) | |
37 | + p.expects(:category_name).returns('Software').at_least_once | |
38 | + p.name = 'Software' | |
39 | + p.save | |
40 | + assert_equal 'Software', p.name | |
41 | + assert_equal nil, p[:name] | |
42 | + end | |
43 | + | |
23 | 44 | should 'list recent products' do |
24 | 45 | enterprise = fast_create(Enterprise, :name => "My enterprise", :identifier => 'my-enterprise') |
25 | 46 | Product.delete_all |
... | ... | @@ -113,7 +134,7 @@ class ProductTest < Test::Unit::TestCase |
113 | 134 | |
114 | 135 | product.expects(:id).returns(999) |
115 | 136 | product.expects(:enterprise).returns(enterprise) |
116 | - assert_equal({:controller => 'catalog', :action => 'show', :id => 999}, product.url) | |
137 | + assert_equal({:controller => 'manage_products', :action => 'show', :id => 999}, product.url) | |
117 | 138 | end |
118 | 139 | |
119 | 140 | should 'categorize also with product categorization' do |
... | ... | @@ -178,12 +199,27 @@ class ProductTest < Test::Unit::TestCase |
178 | 199 | end |
179 | 200 | end |
180 | 201 | |
202 | + should 'accept discount in american\'s or brazilian\'s currency format' do | |
203 | + [ | |
204 | + [12.34, 12.34], | |
205 | + ["12.34", 12.34], | |
206 | + ["12,34", 12.34], | |
207 | + ["12.345.678,90", 12345678.90], | |
208 | + ["12,345,678.90", 12345678.90], | |
209 | + ["12.345.678", 12345678.00], | |
210 | + ["12,345,678", 12345678.00] | |
211 | + ].each do |input, output| | |
212 | + product = Product.new(:discount => input) | |
213 | + assert_equal output, product.discount | |
214 | + end | |
215 | + end | |
216 | + | |
181 | 217 | should 'strip name with malformed HTML when sanitize' do |
182 | 218 | product = Product.new(:product_category => @product_category) |
183 | 219 | product.name = "<h1 Bla </h1>" |
184 | 220 | product.valid? |
185 | 221 | |
186 | - assert_equal '', product.name | |
222 | + assert_equal @product_category.name, product.name | |
187 | 223 | end |
188 | 224 | |
189 | 225 | should 'escape malformed html tags' do |
... | ... | @@ -208,4 +244,23 @@ class ProductTest < Test::Unit::TestCase |
208 | 244 | assert product.errors.invalid?(:product_category) |
209 | 245 | end |
210 | 246 | |
247 | + should 'format values to float with 2 decimals' do | |
248 | + ent = fast_create(Enterprise, :name => 'test ent 1', :identifier => 'test_ent1') | |
249 | + product = fast_create(Product, :enterprise_id => ent.id, :price => 12.994, :discount => 1.994) | |
250 | + | |
251 | + assert_equal "12.99", product.formatted_value(:price) | |
252 | + assert_equal "1.99", product.formatted_value(:discount) | |
253 | + end | |
254 | + | |
255 | + should 'calculate price with discount' do | |
256 | + ent = fast_create(Enterprise, :name => 'test ent 1', :identifier => 'test_ent1') | |
257 | + product = fast_create(Product, :enterprise_id => ent.id, :price => 12.994, :discount => 1.994) | |
258 | + | |
259 | + assert_equal 11.00, product.price_with_discount | |
260 | + end | |
261 | + | |
262 | + should 'have default image' do | |
263 | + product = Product.new | |
264 | + assert_equal '/images/icons-app/product-default-pic-thumb.png', product.default_image | |
265 | + end | |
211 | 266 | end | ... | ... |