comparison app/helpers/.svn/text-base/application_helper.rb.svn-base @ 441:cbce1fd3b1b7 redmine-1.2

Update to Redmine 1.2-stable branch (Redmine SVN rev 6000)
author Chris Cannam
date Mon, 06 Jun 2011 14:24:13 +0100
parents 051f544170fe
children 753f1380d6bc
comparison
equal deleted inserted replaced
245:051f544170fe 441:cbce1fd3b1b7
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 # 3 #
4 # This program is free software; you can redistribute it and/or 4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License 5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2 6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version. 7 # of the License, or (at your option) any later version.
61 end 61 end
62 end 62 end
63 63
64 # Displays a link to +issue+ with its subject. 64 # Displays a link to +issue+ with its subject.
65 # Examples: 65 # Examples:
66 # 66 #
67 # link_to_issue(issue) # => Defect #6: This is the subject 67 # link_to_issue(issue) # => Defect #6: This is the subject
68 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i... 68 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
69 # link_to_issue(issue, :subject => false) # => Defect #6 69 # link_to_issue(issue, :subject => false) # => Defect #6
70 # link_to_issue(issue, :project => true) # => Foo - Defect #6 70 # link_to_issue(issue, :project => true) # => Foo - Defect #6
71 # 71 #
78 subject = issue.subject 78 subject = issue.subject
79 if options[:truncate] 79 if options[:truncate]
80 subject = truncate(subject, :length => options[:truncate]) 80 subject = truncate(subject, :length => options[:truncate])
81 end 81 end
82 end 82 end
83 s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, 83 s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
84 :class => issue.css_classes, 84 :class => issue.css_classes,
85 :title => title 85 :title => title
86 s << ": #{h subject}" if subject 86 s << ": #{h subject}" if subject
87 s = "#{h issue.project} - " + s if options[:project] 87 s = "#{h issue.project} - " + s if options[:project]
88 s 88 s
107 rev = revision.respond_to?(:identifier) ? revision.identifier : revision 107 rev = revision.respond_to?(:identifier) ? revision.identifier : revision
108 108
109 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev}, 109 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev},
110 :title => l(:label_revision_id, format_revision(revision))) 110 :title => l(:label_revision_id, format_revision(revision)))
111 end 111 end
112 112
113 # Generates a link to a message 113 # Generates a link to a message
114 def link_to_message(message, options={}, html_options = nil) 114 def link_to_message(message, options={}, html_options = nil)
115 link_to( 115 link_to(
116 h(truncate(message.subject, :length => 60)), 116 h(truncate(message.subject, :length => 60)),
117 { :controller => 'messages', :action => 'show', 117 { :controller => 'messages', :action => 'show',
124 ) 124 )
125 end 125 end
126 126
127 # Generates a link to a project if active 127 # Generates a link to a project if active
128 # Examples: 128 # Examples:
129 # 129 #
130 # link_to_project(project) # => link to the specified project overview 130 # link_to_project(project) # => link to the specified project overview
131 # link_to_project(project, :action=>'settings') # => link to project settings 131 # link_to_project(project, :action=>'settings') # => link to project settings
132 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options 132 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
133 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) 133 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
134 # 134 #
158 158
159 def prompt_to_remote(name, text, param, url, html_options = {}) 159 def prompt_to_remote(name, text, param, url, html_options = {})
160 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;" 160 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
161 link_to name, {}, html_options 161 link_to name, {}, html_options
162 end 162 end
163 163
164 def format_activity_title(text) 164 def format_activity_title(text)
165 h(truncate_single_line(text, :length => 100)) 165 h(truncate_single_line(text, :length => 100))
166 end 166 end
167 167
168 def format_activity_day(date) 168 def format_activity_day(date)
169 date == Date.today ? l(:label_today).titleize : format_date(date) 169 date == Date.today ? l(:label_today).titleize : format_date(date)
170 end 170 end
171 171
172 def format_activity_description(text) 172 def format_activity_description(text)
173 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />") 173 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
174 end 174 end
175 175
176 def format_version_name(version) 176 def format_version_name(version)
178 h(version) 178 h(version)
179 else 179 else
180 h("#{version.project} - #{version}") 180 h("#{version.project} - #{version}")
181 end 181 end
182 end 182 end
183 183
184 def due_date_distance_in_words(date) 184 def due_date_distance_in_words(date)
185 if date 185 if date
186 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) 186 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
187 end 187 end
188 end 188 end
189 189
190 def render_page_hierarchy(pages, node=nil) 190 def render_page_hierarchy(pages, node=nil, options={})
191 content = '' 191 content = ''
192 if pages[node] 192 if pages[node]
193 content << "<ul class=\"pages-hierarchy\">\n" 193 content << "<ul class=\"pages-hierarchy\">\n"
194 pages[node].each do |page| 194 pages[node].each do |page|
195 content << "<li>" 195 content << "<li>"
196 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}, 196 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title},
197 :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil)) 197 :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
198 content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id] 198 content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
199 content << "</li>\n" 199 content << "</li>\n"
200 end 200 end
201 content << "</ul>\n" 201 content << "</ul>\n"
202 end 202 end
203 content 203 content
204 end 204 end
205 205
206 # Renders flash messages 206 # Renders flash messages
207 def render_flash_messages 207 def render_flash_messages
208 s = '' 208 s = ''
209 flash.each do |k,v| 209 flash.each do |k,v|
210 s << content_tag('div', v, :class => "flash #{k}") 210 s << content_tag('div', v, :class => "flash #{k}")
211 end 211 end
212 s 212 s
213 end 213 end
214 214
215 # Renders tabs and their content 215 # Renders tabs and their content
216 def render_tabs(tabs) 216 def render_tabs(tabs)
217 if tabs.any? 217 if tabs.any?
218 render :partial => 'common/tabs', :locals => {:tabs => tabs} 218 render :partial => 'common/tabs', :locals => {:tabs => tabs}
219 else 219 else
220 content_tag 'p', l(:label_no_data), :class => "nodata" 220 content_tag 'p', l(:label_no_data), :class => "nodata"
221 end 221 end
222 end 222 end
223 223
224 # Renders the project quick-jump box 224 # Renders the project quick-jump box
225 def render_project_jump_box 225 def render_project_jump_box
226 # Retrieve them now to avoid a COUNT query 226 return unless User.current.logged?
227 projects = User.current.projects.all 227 projects = User.current.memberships.collect(&:project).compact.uniq
228 if projects.any? 228 if projects.any?
229 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' + 229 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' +
230 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" + 230 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
231 '<option value="" disabled="disabled">---</option>' 231 '<option value="" disabled="disabled">---</option>'
232 s << project_tree_options_for_select(projects, :selected => @project) do |p| 232 s << project_tree_options_for_select(projects, :selected => @project) do |p|
234 end 234 end
235 s << '</select>' 235 s << '</select>'
236 s 236 s
237 end 237 end
238 end 238 end
239 239
240 def project_tree_options_for_select(projects, options = {}) 240 def project_tree_options_for_select(projects, options = {})
241 s = '' 241 s = ''
242 project_tree(projects) do |project, level| 242 project_tree(projects) do |project, level|
243 name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ') : '') 243 name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ') : '')
244 tag_options = {:value => project.id} 244 tag_options = {:value => project.id}
250 tag_options.merge!(yield(project)) if block_given? 250 tag_options.merge!(yield(project)) if block_given?
251 s << content_tag('option', name_prefix + h(project), tag_options) 251 s << content_tag('option', name_prefix + h(project), tag_options)
252 end 252 end
253 s 253 s
254 end 254 end
255 255
256 # Yields the given block for each project with its level in the tree 256 # Yields the given block for each project with its level in the tree
257 # 257 #
258 # Wrapper for Project#project_tree 258 # Wrapper for Project#project_tree
259 def project_tree(projects, &block) 259 def project_tree(projects, &block)
260 Project.project_tree(projects, &block) 260 Project.project_tree(projects, &block)
261 end 261 end
262 262
263 def project_nested_ul(projects, &block) 263 def project_nested_ul(projects, &block)
264 s = '' 264 s = ''
265 if projects.any? 265 if projects.any?
266 ancestors = [] 266 ancestors = []
267 projects.sort_by(&:lft).each do |project| 267 projects.sort_by(&:lft).each do |project|
268 if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) 268 if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
269 s << "<ul>\n" 269 s << "<ul>\n"
270 else 270 else
271 ancestors.pop 271 ancestors.pop
272 s << "</li>" 272 s << "</li>"
273 while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) 273 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
274 ancestors.pop 274 ancestors.pop
275 s << "</ul></li>\n" 275 s << "</ul></li>\n"
276 end 276 end
277 end 277 end
278 s << "<li>" 278 s << "<li>"
281 end 281 end
282 s << ("</li></ul>\n" * ancestors.size) 282 s << ("</li></ul>\n" * ancestors.size)
283 end 283 end
284 s 284 s
285 end 285 end
286 286
287 def principals_check_box_tags(name, principals) 287 def principals_check_box_tags(name, principals)
288 s = '' 288 s = ''
289 principals.sort.each do |principal| 289 principals.sort.each do |principal|
290 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" 290 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n"
291 end 291 end
292 s 292 s
293 end 293 end
294 294
295 # Truncates and returns the string as a single line 295 # Truncates and returns the string as a single line
296 def truncate_single_line(string, *args) 296 def truncate_single_line(string, *args)
297 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') 297 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
298 end 298 end
299 299
300 # Truncates at line break after 250 characters or options[:length] 300 # Truncates at line break after 250 characters or options[:length]
301 def truncate_lines(string, options={}) 301 def truncate_lines(string, options={})
302 length = options[:length] || 250 302 length = options[:length] || 250
303 if string.to_s =~ /\A(.{#{length}}.*?)$/m 303 if string.to_s =~ /\A(.{#{length}}.*?)$/m
304 "#{$1}..." 304 "#{$1}..."
312 end 312 end
313 313
314 def authoring(created, author, options={}) 314 def authoring(created, author, options={})
315 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)) 315 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))
316 end 316 end
317 317
318 def time_tag(time) 318 def time_tag(time)
319 text = distance_of_time_in_words(Time.now, time) 319 text = distance_of_time_in_words(Time.now, time)
320 if @project 320 if @project
321 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time)) 321 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time))
322 else 322 else
334 334
335 def pagination_links_full(paginator, count=nil, options={}) 335 def pagination_links_full(paginator, count=nil, options={})
336 page_param = options.delete(:page_param) || :page 336 page_param = options.delete(:page_param) || :page
337 per_page_links = options.delete(:per_page_links) 337 per_page_links = options.delete(:per_page_links)
338 url_param = params.dup 338 url_param = params.dup
339 # don't reuse query params if filters are present
340 url_param.merge!(:fields => nil, :values => nil, :operators => nil) if url_param.delete(:set_filter)
341 339
342 html = '' 340 html = ''
343 if paginator.current.previous 341 if paginator.current.previous
344 html << link_to_remote_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' 342 html << link_to_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' '
345 end 343 end
346 344
347 html << (pagination_links_each(paginator, options) do |n| 345 html << (pagination_links_each(paginator, options) do |n|
348 link_to_remote_content_update(n.to_s, url_param.merge(page_param => n)) 346 link_to_content_update(n.to_s, url_param.merge(page_param => n))
349 end || '') 347 end || '')
350 348
351 if paginator.current.next 349 if paginator.current.next
352 html << ' ' + link_to_remote_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next)) 350 html << ' ' + link_to_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next))
353 end 351 end
354 352
355 unless count.nil? 353 unless count.nil?
356 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})" 354 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})"
357 if per_page_links != false && links = per_page_links(paginator.items_per_page) 355 if per_page_links != false && links = per_page_links(paginator.items_per_page)
359 end 357 end
360 end 358 end
361 359
362 html 360 html
363 end 361 end
364 362
365 def per_page_links(selected=nil) 363 def per_page_links(selected=nil)
366 url_param = params.dup
367 url_param.clear if url_param.has_key?(:set_filter)
368
369 links = Setting.per_page_options_array.collect do |n| 364 links = Setting.per_page_options_array.collect do |n|
370 n == selected ? n : link_to_remote(n, {:update => "content", 365 n == selected ? n : link_to_content_update(n, params.merge(:per_page => n))
371 :url => params.dup.merge(:per_page => n),
372 :method => :get},
373 {:href => url_for(url_param.merge(:per_page => n))})
374 end 366 end
375 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil 367 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
376 end 368 end
377 369
378 def reorder_links(name, url) 370 def reorder_links(name, url)
379 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) + 371 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) +
380 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) + 372 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) +
381 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) + 373 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) +
382 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest)) 374 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest))
384 376
385 def breadcrumb(*args) 377 def breadcrumb(*args)
386 elements = args.flatten 378 elements = args.flatten
387 elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil 379 elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil
388 end 380 end
389 381
390 def other_formats_links(&block) 382 def other_formats_links(&block)
391 concat('<p class="other-formats">' + l(:label_export_to)) 383 concat('<p class="other-formats">' + l(:label_export_to))
392 yield Redmine::Views::OtherFormatsBuilder.new(self) 384 yield Redmine::Views::OtherFormatsBuilder.new(self)
393 concat('</p>') 385 concat('</p>')
394 end 386 end
395 387
396 def page_header_title 388 def page_header_title
397 if @project.nil? || @project.new_record? 389 if @project.nil? || @project.new_record?
398 h(Setting.app_title) 390 h(Setting.app_title)
399 else 391 else
400 b = [] 392 b = []
401 ancestors = (@project.root? ? [] : @project.ancestors.visible) 393 ancestors = (@project.root? ? [] : @project.ancestors.visible.all)
402 if ancestors.any? 394 if ancestors.any?
403 root = ancestors.shift 395 root = ancestors.shift
404 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') 396 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
405 if ancestors.size > 2 397 if ancestors.size > 2
406 b << '&#8230;' 398 b << '&#8230;'
463 return '' if text.blank? 455 return '' if text.blank?
464 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) 456 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
465 only_path = options.delete(:only_path) == false ? false : true 457 only_path = options.delete(:only_path) == false ? false : true
466 458
467 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } 459 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
468 460
469 @parsed_headings = [] 461 @parsed_headings = []
470 text = parse_non_pre_blocks(text) do |text| 462 text = parse_non_pre_blocks(text) do |text|
471 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name| 463 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
472 send method_name, text, project, obj, attr, only_path, options 464 send method_name, text, project, obj, attr, only_path, options
473 end 465 end
474 end 466 end
475 467
476 if @parsed_headings.any? 468 if @parsed_headings.any?
477 replace_toc(text, @parsed_headings) 469 replace_toc(text, @parsed_headings)
478 end 470 end
479 471
480 text 472 text
481 end 473 end
482 474
483 def parse_non_pre_blocks(text) 475 def parse_non_pre_blocks(text)
484 s = StringScanner.new(text) 476 s = StringScanner.new(text)
485 tags = [] 477 tags = []
486 parsed = '' 478 parsed = ''
487 while !s.eos? 479 while !s.eos?
506 while tag = tags.pop 498 while tag = tags.pop
507 parsed << "</#{tag}>" 499 parsed << "</#{tag}>"
508 end 500 end
509 parsed 501 parsed
510 end 502 end
511 503
512 def parse_inline_attachments(text, project, obj, attr, only_path, options) 504 def parse_inline_attachments(text, project, obj, attr, only_path, options)
513 # when using an image link, try to use an attachment, if possible 505 # when using an image link, try to use an attachment, if possible
514 if options[:attachments] || (obj && obj.respond_to?(:attachments)) 506 if options[:attachments] || (obj && obj.respond_to?(:attachments))
515 attachments = nil 507 attachments = nil
516 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| 508 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
517 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 509 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
518 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse 510 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse
519 # search for the picture in attachments 511 # search for the picture in attachments
520 if found = attachments.detect { |att| att.filename.downcase == filename } 512 if found = attachments.detect { |att| att.filename.downcase == filename }
521 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found 513 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
522 desc = found.description.to_s.gsub('"', '') 514 desc = found.description.to_s.gsub('"', '')
575 else 567 else
576 all 568 all
577 end 569 end
578 end 570 end
579 end 571 end
580 572
581 # Redmine links 573 # Redmine links
582 # 574 #
583 # Examples: 575 # Examples:
584 # Issues: 576 # Issues:
585 # #52 -> Link to issue #52 577 # #52 -> Link to issue #52
698 end 690 end
699 end 691 end
700 leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}") 692 leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}")
701 end 693 end
702 end 694 end
703 695
704 HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE) 696 HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE)
705 697
706 # Headings and TOC 698 # Headings and TOC
707 # Adds ids and links to headings unless options[:headings] is set to false 699 # Adds ids and links to headings unless options[:headings] is set to false
708 def parse_headings(text, project, obj, attr, only_path, options) 700 def parse_headings(text, project, obj, attr, only_path, options)
709 return if options[:headings] == false 701 return if options[:headings] == false
710 702
711 text.gsub!(HEADING_RE) do 703 text.gsub!(HEADING_RE) do
712 level, attrs, content = $1.to_i, $2, $3 704 level, attrs, content = $1.to_i, $2, $3
713 item = strip_tags(content).strip 705 item = strip_tags(content).strip
714 anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') 706 anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
715 @parsed_headings << [level, anchor, item] 707 @parsed_headings << [level, anchor, item]
716 "<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>" 708 "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
717 end 709 end
718 end 710 end
719 711
720 TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) 712 TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
721 713
722 # Renders the TOC with given headings 714 # Renders the TOC with given headings
723 def replace_toc(text, headings) 715 def replace_toc(text, headings)
724 text.gsub!(TOC_RE) do 716 text.gsub!(TOC_RE) do
725 if headings.empty? 717 if headings.empty?
726 '' 718 ''
799 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') + 791 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') +
800 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '') 792 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '')
801 ), :class => 'progress', :style => "width: #{width};") + 793 ), :class => 'progress', :style => "width: #{width};") +
802 content_tag('p', legend, :class => 'pourcent') 794 content_tag('p', legend, :class => 'pourcent')
803 end 795 end
804 796
805 def checked_image(checked=true) 797 def checked_image(checked=true)
806 if checked 798 if checked
807 image_tag 'toggle_check.png' 799 image_tag 'toggle_check.png'
808 end 800 end
809 end 801 end
810 802
811 def context_menu(url) 803 def context_menu(url)
812 unless @context_menu_included 804 unless @context_menu_included
813 content_for :header_tags do 805 content_for :header_tags do
814 javascript_include_tag('context_menu') + 806 javascript_include_tag('context_menu') +
815 stylesheet_link_tag('context_menu') 807 stylesheet_link_tag('context_menu')
853 start_of_week = case Setting.start_of_week.to_i 845 start_of_week = case Setting.start_of_week.to_i
854 when 1 846 when 1
855 'Calendar._FD = 1;' # Monday 847 'Calendar._FD = 1;' # Monday
856 when 7 848 when 7
857 'Calendar._FD = 0;' # Sunday 849 'Calendar._FD = 0;' # Sunday
850 when 6
851 'Calendar._FD = 6;' # Saturday
858 else 852 else
859 '' # use language 853 '' # use language
860 end 854 end
861 855
862 javascript_include_tag('calendar/calendar') + 856 javascript_include_tag('calendar/calendar') +
863 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") + 857 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") +
864 javascript_tag(start_of_week) + 858 javascript_tag(start_of_week) +
865 javascript_include_tag('calendar/calendar-setup') + 859 javascript_include_tag('calendar/calendar-setup') +
866 stylesheet_link_tag('calendar') 860 stylesheet_link_tag('calendar')
867 end 861 end
868 end 862 end
869 end 863 end
892 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil 886 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
893 else 887 else
894 '' 888 ''
895 end 889 end
896 end 890 end
897 891
898 # Returns the javascript tags that are included in the html layout head 892 # Returns the javascript tags that are included in the html layout head
899 def javascript_heads 893 def javascript_heads
900 tags = javascript_include_tag(:defaults) 894 tags = javascript_include_tag(:defaults)
901 unless User.current.pref.warn_on_leaving_unsaved == '0' 895 unless User.current.pref.warn_on_leaving_unsaved == '0'
902 tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") 896 tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
905 end 899 end
906 900
907 def favicon 901 def favicon
908 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />" 902 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
909 end 903 end
910 904
905 def robot_exclusion_tag
906 '<meta name="robots" content="noindex,follow,noarchive" />'
907 end
908
911 # Returns true if arg is expected in the API response 909 # Returns true if arg is expected in the API response
912 def include_in_api_response?(arg) 910 def include_in_api_response?(arg)
913 unless @included_in_api_response 911 unless @included_in_api_response
914 param = params[:include] 912 param = params[:include]
915 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') 913 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
927 nil 925 nil
928 else 926 else
929 options 927 options
930 end 928 end
931 end 929 end
932 930
933 private 931 private
934 932
935 def wiki_helper 933 def wiki_helper
936 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) 934 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
937 extend helper 935 extend helper
938 return self 936 return self
939 end 937 end
940 938
941 def link_to_remote_content_update(text, url_params) 939 def link_to_content_update(text, url_params = {}, html_options = {})
942 link_to_remote(text, 940 link_to(text, url_params, html_options)
943 {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, 941 end
944 {:href => url_for(:params => url_params)}
945 )
946 end
947
948 end 942 end