Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
Index: /home/mislav/projects/radiant/app/controllers/application.rb =================================================================== --- /home/mislav/projects/radiant/app/controllers/application.rb (revision 573) +++ /home/mislav/projects/radiant/app/controllers/application.rb (working copy) @@ -1,9 +1,5 @@ require_dependency 'radiant' -ActionView::Base.field_error_proc = Proc.new do |html, instance| - %{<div class="error-with-field">#{html} <small class="error">• #{[instance.error_message].flatten.first}</small></div>} -end - class ApplicationController < ActionController::Base include LoginSystem @@ -19,7 +15,9 @@ @config = Radiant::Config end + # helpers to include additional assets from actions or views helper_method :include_stylesheet, :include_javascript + def include_stylesheet(sheet) @stylesheets << sheet end @@ -36,6 +34,7 @@ super end end + private def set_current_user @@ -43,7 +42,7 @@ end def set_javascripts_and_stylesheets - @stylesheets = ['admin/main'] - @javascripts = ['prototype', 'string', 'effects', 'dragdrop', 'controls', 'tabcontrol', 'ruledtable'] + @stylesheets = %w(admin/main) + @javascripts = %w(prototype string effects tabcontrol ruledtable admin) end end Index: /home/mislav/projects/radiant/app/controllers/admin/page_controller.rb =================================================================== --- /home/mislav/projects/radiant/app/controllers/admin/page_controller.rb (revision 573) +++ /home/mislav/projects/radiant/app/controllers/admin/page_controller.rb (working copy) @@ -47,6 +47,7 @@ def add_part part = PagePart.new(params[:part]) + @index = params[:index].to_i if params[:index] render(:partial => 'part', :object => part, :layout => false) end Index: /home/mislav/projects/radiant/app/controllers/admin/user_controller.rb =================================================================== --- /home/mislav/projects/radiant/app/controllers/admin/user_controller.rb (revision 573) +++ /home/mislav/projects/radiant/app/controllers/admin/user_controller.rb (working copy) @@ -1,7 +1,8 @@ class Admin::UserController < Admin::AbstractModelController model_class User - only_allow_access_to :index, :new, :edit, :remove, :when => :admin, + only_allow_access_to :index, :new, :edit, :remove, + :when => :admin, :denied_url => {:controller => 'page', :action => :index}, :denied_message => 'You must have administrative privileges to perform this action.' Index: /home/mislav/projects/radiant/app/controllers/admin/export_controller.rb =================================================================== --- /home/mislav/projects/radiant/app/controllers/admin/export_controller.rb (revision 573) +++ /home/mislav/projects/radiant/app/controllers/admin/export_controller.rb (working copy) @@ -1,6 +1,6 @@ class Admin::ExportController < ApplicationController def yaml response.headers['Content-Type'] = "text/yaml" - render_text Radiant::Exporter.export + render :text => Radiant::Exporter.export end end Index: /home/mislav/projects/radiant/app/views/admin/page/_part.rhtml =================================================================== --- /home/mislav/projects/radiant/app/views/admin/page/_part.rhtml (revision 573) +++ /home/mislav/projects/radiant/app/views/admin/page/_part.rhtml (working copy) @@ -1,18 +1,13 @@ -<% -@part = part -@index = (params[:index] || @index || 1).to_i --%> -<div class="page" id="page-<%= @index %>"> - <div class="part" id="part-<%= @index %>"> - <%= hidden_field_tag "part[#{@index - 1}][name]", @part.name %> +<% @index ||= 0 -%> +<div class="page" id="page-<%= @index + 1 %>"> + <div class="part" id="part-<%= @index + 1 %>"> + <%= hidden_field_tag "part[#{@index}][name]", part.name %> <p> - <label for="part[<%= @index - 1 %>][filter_id]">Filter</label> - <%= select_tag "part[#{@index - 1}][filter_id]", options_for_select([['<none>', '']] + TextFilter.descendants.map { |s| s.filter_name }.sort, @part.filter_id) %> - <span id="reference-links">Reference: <span id="filter-reference-link-<%= @index-1 %>"><%= link_to_function "Filter", "load_filter_reference(#{@index - 1})" %></span> <span id="tag-reference-link-<%= @index -1 %>"><%= link_to_function 'Available Tags', "load_tag_reference(#{@index-1});" %></span></span> + <label for="part[<%= @index %>][filter_id]">Filter</label> + <%= select_tag "part[#{@index}][filter_id]", options_for_select([['<none>', '']] + TextFilter.descendants.map { |s| s.filter_name }.sort, part.filter_id) %> + <span id="reference-links">Reference: <span id="filter-reference-link-<%= @index %>"><%= link_to_function "Filter", "load_filter_reference(#{@index})" %></span> <span id="tag-reference-link-<%= @index %>"><%= link_to_function 'Available Tags', "load_tag_reference(#{@index});" %></span></span> </p> - <div><%= text_area_tag "part[#{@index - 1}][content]", h(@part.content), :class => "textarea", :style => "width: 100%" %></div> + <div><%= text_area_tag "part[#{@index}][content]", h(part.content), :class => "textarea", :style => "width: 100%" %></div> </div> </div> -<% -@index += 1; --%> \ No newline at end of file +<% @index += 1 -%> Index: /home/mislav/projects/radiant/app/views/admin/page/edit.rhtml =================================================================== --- /home/mislav/projects/radiant/app/views/admin/page/edit.rhtml (revision 573) +++ /home/mislav/projects/radiant/app/views/admin/page/edit.rhtml (working copy) @@ -1,87 +1,34 @@ <% content_for('page_scripts') do -%> - function part_added() { - var partNameField = $('part-name-field'); - var partIndexField = $('part-index-field'); - var index = parseInt(partIndexField.value); - var tab = 'tab-' + index; - var caption = partNameField.value; - var page = 'page-' + index; - tabControl.addTab(tab, caption, page); - Element.hide('add-part-popup'); - Element.hide('busy'); - partNameField.value = ''; - partIndexField.value = (index + 1).toString(); - $('add-part-button').disabled = false; - Field.focus(partNameField); - tabControl.select(tab); - } - function part_loading() { - $('add-part-button').disabled = true; - new Effect.Appear('busy'); - } - function valid_part_name() { - var partNameField = $('part-name-field'); - var name = partNameField.value.downcase().strip(); - var result = true; - if (name == '') { - alert('Part name cannot be empty.'); - return false; - } - tabControl.tabs.each(function(pair){ - if (tabControl.tabs.get(pair.key).caption == name) { - result = false; - alert('Part name must be unique.'); - throw $break; - } - }) - return result; - } - function center(element) { - var header = $('header') - element = $(element); - element.style.position = 'absolute'; - var dim = Element.getDimensions(element); - var top = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; - element.style.top = (top + 200) + 'px'; - element.style.left = ((header.offsetWidth - dim.width) / 2) + 'px'; - } - function toggle_add_part_popup() { - var popup = $('add-part-popup'); - var partNameField = $('part-name-field'); - center(popup); - Element.toggle(popup); - Field.focus(partNameField); - } - var last_type = "<%= @page.class_name %>"; - function load_tag_reference(part) { - page_type = $F('page_class_name'); - popup = $('tag-reference-popup'); - if(last_type != page_type) { - url = "<%= tag_reference_url %>"; - params = "class_name=" + page_type; - new Effect.Highlight('tag-reference-link-'+ part); - req = new Ajax.Request(url, { method: 'get', parameters: params, evalScripts: true }); - } else { - center(popup); - Element.toggle(popup); - } - return false; - } - var last_filter = "<%= default_filter_name %>"; - function load_filter_reference(part) { - filter_type = $F("part[" + part + "][filter_id]"); - popup = $('filter-reference-popup'); - if(last_filter != filter_type) { - url = "<%= filter_reference_url %>"; - params = "filter_name=" + filter_type; - new Effect.Highlight('filter-reference-link-'+ part); - req = new Ajax.Request(url, { method: 'get', parameters: params, evalScripts: true }); - } else { - center(popup); - Element.toggle(popup); - } - return false; - } + var last_type = "<%= @page.class_name %>"; + function load_tag_reference(part) { + page_type = $F('page_class_name'); + popup = $('tag-reference-popup'); + if(last_type != page_type) { + url = "<%= tag_reference_url %>"; + params = "class_name=" + page_type; + new Effect.Highlight('tag-reference-link-'+ part); + req = new Ajax.Request(url, { method: 'get', parameters: params, evalScripts: true }); + } else { + center(popup); + Element.toggle(popup); + } + return false; + } + var last_filter = "<%= default_filter_name %>"; + function load_filter_reference(part) { + filter_type = $F("part[" + part + "][filter_id]"); + popup = $('filter-reference-popup'); + if(last_filter != filter_type) { + url = "<%= filter_reference_url %>"; + params = "filter_name=" + filter_type; + new Effect.Highlight('filter-reference-link-'+ part); + req = new Ajax.Request(url, { method: 'get', parameters: params, evalScripts: true }); + } else { + center(popup); + Element.toggle(popup); + } + return false; + } <% end -%> <% content_for :page_css do %> @@ -115,25 +62,11 @@ <%= text_field "page", "title", :class => 'textbox', :maxlength => 255 %> </p> <div id="extended-metadata" class="row"<%= meta_visible(:meta) %>> - <table class="fieldset" cellpadding="0" cellspacing="0" border="0"> + <table class="fieldset"> <% for meta in @meta %> <%= render :partial => "meta_row", :object => meta %> <% end %> </table> - <script type="text/javascript"> - // <![CDATA[ - $title = $('page_title'); - $slug = $('page_slug'); - $breadcrumb = $('page_breadcrumb'); - $old_title = $title.value || ''; - function title_updated() { - if ($old_title.toSlug() == $slug.value) $slug.value = $title.value.toSlug(); - if ($old_title == $breadcrumb.value) $breadcrumb.value = $title.value; - $old_title = $title.value; - } - new Form.Element.Observer('page_title', 0.15, title_updated); - // ]]> - </script> </div> <p class="more-or-less"> <small> @@ -152,21 +85,7 @@ <%= render :partial => 'part', :collection => @page.parts %> </div> </div> - <script type="text/javascript"> - // <![CDATA[ - var tabControl = new TabControl('tab-control'); -<% -@index = 0 -for @part in @page.parts do - @index += 1 --%> - tabControl.addTab('tab-<%= @index %>', '<%= @part.name %>', 'page-<%= @index %>'); -<% -end --%> - tabControl.select(tabControl.firstTab()); - // ]]> - </script> + <div class="row"> <p><label for="page_layout_id">Layout</label> <%= select "page", "layout_id", [['<inherit>', '']] + Layout.find(:all).map { |s| [s.name, s.id] } %></p> @@ -199,11 +118,11 @@ :condition => 'valid_part_name()' ) do %> <div> - <%= hidden_field_tag 'index', @index + 1, :id => 'part-index-field' %> + <%= hidden_field_tag 'index', @index, :id => 'part-index-field' %> <%= text_field_tag "part[name]", "", :id => 'part-name-field', :maxlength => 100 %> <%= submit_tag "Add Part", :id => 'add-part-button' %> </div> - <p><%= link_to_function 'Close', "Element.hide('add-part-popup')", :class => 'close-link' %></p> + <p><%= link_to_function 'Close', "$(this).up('.popup').hide()", :class => 'close-link' %></p> <% end %> </div> <div class="popup" id="tag-reference-popup" style="display:none;"> @@ -219,5 +138,3 @@ <p><%= link_to_function 'Close', "Element.hide('filter-reference-popup')", :class => 'close-link' %></p> </div> <% end -%> - -<%= focus 'page_title' %> Index: /home/mislav/projects/radiant/app/views/admin/page/index.rhtml =================================================================== --- /home/mislav/projects/radiant/app/views/admin/page/index.rhtml (revision 573) +++ /home/mislav/projects/radiant/app/views/admin/page/index.rhtml (working copy) @@ -2,7 +2,7 @@ <h1>Pages</h1> -<table id="site-map" class="index" cellpadding="0" cellspacing="0" border="0"> +<table id="site-map" class="index" summary="Page hierarchy of the current site"> <thead> <tr> <th class="page">Page</th> @@ -20,11 +20,7 @@ <% end -%> </tbody> </table> -<script type="text/javascript"> -// <![CDATA[ - new SiteMap('site-map', <%= expanded_rows.to_json %>); -// ]]> -</script> + <form action="<%= clear_cache_url %>" method="post"> <p> <% unless @homepage -%> Index: /home/mislav/projects/radiant/config/environment.rb =================================================================== --- /home/mislav/projects/radiant/config/environment.rb (revision 573) +++ /home/mislav/projects/radiant/config/environment.rb (working copy) @@ -67,12 +67,13 @@ # Auto-require text filters Dir["#{RADIANT_ROOT}/app/models/*_filter.rb"].each do |filter| - filter = $1 if filter =~ %r{/([^/]+)\.rb} - require_dependency filter + require_dependency File.basename(filter).sub(/\.rb$/, '') end # Response Caching Defaults ResponseCache.defaults[:directory] = ActionController::Base.page_cache_directory ResponseCache.defaults[:logger] = ActionController::Base.logger -require "status" +ActionView::Base.field_error_proc = Proc.new do |html, instance| + %{<div class="error-with-field">#{html} <small class="error">• #{[instance.error_message].flatten.first}</small></div>} +end Index: /home/mislav/projects/radiant/public/javascripts/prototype.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/prototype.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/prototype.js (working copy) @@ -21,8 +21,9 @@ XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, SpecificElementExtensions: + document.createElement('div').__proto__ && document.createElement('div').__proto__ !== - document.createElement('form').__proto__ + document.createElement('form').__proto__ }, ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', @@ -561,7 +562,7 @@ var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); - if (match == null) return ''; + if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; @@ -1092,6 +1093,7 @@ } })()); +Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; Hash.from = $H; var ObjectRange = Class.create(Enumerable, { initialize: function(start, end, exclusive) { @@ -1399,8 +1401,10 @@ _getHeaderJSON: function() { var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); try { - return json ? json.evalJSON(this.request.options.sanitizeJSON) : null; + return json.evalJSON(this.request.options.sanitizeJSON); } catch (e) { this.request.dispatchException(e); } @@ -1408,11 +1412,11 @@ _getResponseJSON: function() { var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json'))) + return null; try { - if (options.evalJSON == 'force' || (options.evalJSON && - (this.getHeader('Content-type') || '').include('application/json'))) - return this.transport.responseText.evalJSON(options.sanitizeJSON); - return null; + return this.transport.responseText.evalJSON(options.sanitizeJSON); } catch (e) { this.request.dispatchException(e); } @@ -1859,6 +1863,20 @@ descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (element.sourceIndex) { + var e = element.sourceIndex, a = ancestor.sourceIndex, + nextAncestor = ancestor.nextSibling; + if (!nextAncestor) { + do { ancestor = ancestor.parentNode; } + while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); + } + if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); + } + while (element = element.parentNode) if (element == ancestor) return true; return false; @@ -2248,7 +2266,11 @@ return filter.replace(/alpha\([^\)]*\)/gi,''); } element = $(element); - if (!element.currentStyle.hasLayout) element.style.zoom = 1; + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { (filter = stripAlpha(filter)) ? @@ -2344,7 +2366,7 @@ })(Element._attributeTranslations.read.values); } -else if (Prototype.Browser.Gecko) { +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : @@ -3684,24 +3706,27 @@ }); Event.Methods = (function() { + var isButton; + if (Prototype.Browser.IE) { - function isButton(event, code) { - return event.button == ({ 0: 1, 1: 4, 2: 2 })[code]; - } + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + isButton = function(event, code) { + return event.button == buttonMap[code]; + }; } else if (Prototype.Browser.WebKit) { - function isButton(event, code) { + isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } - } + }; } else { - function isButton(event, code) { + isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); - } + }; } return { @@ -3735,6 +3760,7 @@ Event.extend(event); event.preventDefault(); event.stopPropagation(); + event.stopped = true; } }; })(); @@ -3784,7 +3810,7 @@ } function getDOMEventName(eventName) { - if (eventName && eventName.match(/:/)) return "dataavailable"; + if (eventName && eventName.include(':')) return "dataavailable"; return eventName; } @@ -3803,8 +3829,9 @@ if (c.pluck("handler").include(handler)) return false; var wrapper = function(event) { - if (event.eventName && event.eventName != eventName) - return false; + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; Event.extend(event); handler.call(element, event) Index: /home/mislav/projects/radiant/public/javascripts/tabcontrol.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/tabcontrol.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/tabcontrol.js (working copy) @@ -1,13 +1,13 @@ -TabControl = Class.create({ +var TabControl = Class.create({ /* Initializes a tab control. The variable +element_id+ must be the id of an HTML element containing one element with it's class name set to 'tabs' and another element with it's class name set to 'pages'. */ - initialize: function(element_id) { - TabControl.controls[element_id] = this; - this.control_id = element_id; - this.element = $(element_id); + initialize: function(element) { + this.element = $(element); + this.control_id = this.element.identify(); + TabControl.controls.set(this.control_id, this); this.tab_container = this.element.down('.tabs'); this.tabs = $H(); }, @@ -19,33 +19,24 @@ itself. When a tab is initially added the page element is hidden. */ addTab: function(tab_id, caption, page) { - this.tab_container.insert( - '<a class="tab" href="javascript:TabControl.controls[\'#{id}\'].select(\'#{tab_id}\');">#{caption}</a>'.interpolate({ - id: this.control_id, tab_id: tab_id, caption: caption - }) - ); - var tab = this.tab_container.lastChild; - tab.tab_id = tab_id; - tab.caption = caption; - tab.page = $(page); - this.tabs.set(tab_id, tab); - this._setNotHere(tab); - return tab; + var tab = new TabControl.Tab(this, tab_id, caption, page); + + this.tabs.set(tab.id, tab); + return this.tab_container.appendChild(tab.createElement()); }, /* Removes +tab+. The variable +tab+ may be either a tab ID or a tab element. */ removeTab: function(tab) { - var t = this._tabify(tab); - var id = t.tab_id; - Element.remove(t.page); - Element.remove(t); - this.tabs.unset(id); + if (Object.isString(tab)) tab = this.tabs.get(tab); + tab.remove(); + this.tabs.unset(tab); - if (this.selected.tab_id == id) { + if (this.selected == tab) { var first = this.firstTab(); - if (typeof first != 'undefined') this.select(first.tab_id); + if (first) this.select(first); + else this.selected = null; } }, @@ -54,17 +45,12 @@ tab element. */ select: function(tab) { - var t = this._tabify(tab); - this.tabs.each(function(pair) { - if (pair.key == t.tab_id) { - if (this.selected) this.selected.selected = false; - this.selected = t; - t.selected = true; - this._setHere(pair.key); - } else { - this._setNotHere(pair.key); - } - }, this); + if (Object.isString(tab)) tab = this.tabs.get(tab); + if (this.selected) this.selected.unselect(); + tab.select(); + this.selected = tab; + var persist = this.pageId() + ':' + this.selected.id; + document.cookie = "current_tab=" + persist + "; path=/admin"; }, /* @@ -87,47 +73,53 @@ tabCount: function() { return this.tabs.keys().length; }, - - /* - Private Methods - */ - - /* - Shows the page for +tab+ and adds the class 'here' to tab. The variable +tab+ may - be either a tab ID or a tab element. - */ - _setHere: function(tab) { - var t = this._tabify(tab); - Element.show(t.page); - Element.addClassName(t, 'here'); - }, - - /* - Hides the page for +tab+ and removes the class 'here' from tab. The variable +tab+ - may be either a tab ID or a tab element. - */ - _setNotHere: function(tab) { - var t = this._tabify(tab); - Element.hide(t.page); - Element.removeClassName(t, 'here'); - }, - /* - Returns a tab when passed a string or tab element. Throws a BadTabError otherwise. - */ - _tabify: function(something) { - if (typeof something == 'string') { - var object = this.tabs.get(something); - } else { - var object = something; + autoSelect: function() { + var tab, matches = document.cookie.match(/current_tab=(.+?);/); + if (matches) { + matches = matches[1].split(':'); + var page = matches[0], tabId = matches[1]; + if (!page || page == this.pageId()) tab = this.tabs.get(tabId); } - if ((typeof object != 'undefined') && (object.tab_id)) { - return object; - } else { - throw TabControl.BadTabError; - } + this.select(tab || this.firstTab()); + }, + + pageId: function() { + return /(\d+)/.test(window.location.pathname) ? RegExp.$1 : ''; } }); TabControl.controls = $H(); -TabControl.BadTabError = new Error('TabControl: Invalid tab.'); + +TabControl.Tab = Class.create({ + initialize: function(control, id, label, content) { + this.content = $(content).hide(); + this.label = label || id; + this.id = id; + this.control = control; + }, + + createElement: function() { + return this.element = new Element('a', { className: 'tab', href: '#' }). + update(this.label). + observe('click', function(event){ + this.control.select(this.id); + event.stop(); + }.bindAsEventListener(this)); + }, + + select: function() { + this.content.show(); + this.element.addClassName('here'); + }, + + unselect: function() { + this.content.hide(); + this.element.removeClassName('here'); + }, + + remove: function() { + this.content.remove(); + this.element.stopObserving('click').remove(); + } +}); Index: /home/mislav/projects/radiant/public/javascripts/pngfix.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/pngfix.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/pngfix.js (working copy) @@ -1,39 +1,39 @@ -/* - -Correctly handle PNG transparency in Win IE 5.5 & 6. -http://homepage.ntlworld.com/bobosola. Updated 18-Jan-2006. +/** + * Correctly handle PNG transparency in Win IE 5.5 & 6. + * http://homepage.ntlworld.com/bobosola. Updated 18-Jan-2006. + * + * Use in <HEAD> with DEFER keyword wrapped in conditional comments: + * + * <!--[if lt IE 7]> + * <script defer type="text/javascript" src="pngfix.js"></script> + * <![endif]--> + * + */ -Use in <HEAD> with DEFER keyword wrapped in conditional comments: -<!--[if lt IE 7]> -<script defer type="text/javascript" src="pngfix.js"></script> -<![endif]--> +var arVersion = navigator.appVersion.split("MSIE"), + version = parseFloat(arVersion[1]), + filters = false; + +try { filters = !!document.body.filters } +catch (e) {} -*/ - -var arVersion = navigator.appVersion.split("MSIE") -var version = parseFloat(arVersion[1]) - -if ((version >= 5.5) && (document.body.filters)) -{ - for(var i=0; i<document.images.length; i++) - { - var img = document.images[i] - var imgName = img.src.toUpperCase() - if (imgName.substring(imgName.length-3, imgName.length) == "PNG") - { - var imgID = (img.id) ? "id='" + img.id + "' " : "" - var imgClass = (img.className) ? "class='" + img.className + "' " : "" - var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' " - var imgStyle = "display:inline-block;" + img.style.cssText - if (img.align == "left") imgStyle = "float:left;" + imgStyle - if (img.align == "right") imgStyle = "float:right;" + imgStyle - if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle - var strNewHTML = "<span " + imgID + imgClass + imgTitle - + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";" - + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader" - + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>" - img.outerHTML = strNewHTML - i = i-1 - } - } -} \ No newline at end of file +if (version >= 5.5 && filters) { + $A(document.images).each(function(img) { + if (!img.src.toLowerCase().endsWith('png')) return; + + var span = new Element('span', { id: img.id, className: img.className, title: (img.title || img.alt) }). + setStyle({ + display: 'inline-block', + width: img.width + 'px', + height: img.height + 'px', + filter: 'progid:DXImageTransform.Microsoft.AplhaImageLoader(src="' + img.src + '", sizingMethod="scale")' + }). + setStyle(img.style.cssText); + + if (img.align == "left") span.setStyle("float: left"); + else if (img.align == "right") span.setStyle("float: right"); + if (img.parentElement.href) span.setStyle("cursor: hand"); + + $(img).replace(span); + }); +} Index: /home/mislav/projects/radiant/public/javascripts/tag_reference_search.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/tag_reference_search.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/tag_reference_search.js (working copy) @@ -1,8 +1,8 @@ function hasWordInElement(word, element) { if (element.nodeType == Node.TEXT_NODE) { - return element.nodeValue.match(word) != null; + return element.nodeValue.include(word) != null; } else { - return $A(element.childNodes).any(function (child) { + return $A(element.childNodes).any(function(child) { return hasWordInElement(word, child); }); } Index: /home/mislav/projects/radiant/public/javascripts/sitemap.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/sitemap.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/sitemap.js (working copy) @@ -1,19 +1,15 @@ var SiteMap = Class.create(RuledTable, { - initialize: function($super, id, expanded) { - $super(id); - this.expandedRows = expanded + initialize: function($super, element) { + $super(element); + this.readExpandedCookie(); + Event.observe(element, 'click', this.onMouseClickRow.bindAsEventListener(this)); }, - onRowSetup: function(row) { - Event.observe(row, 'click', this.onMouseClickRow.bindAsEventListener(this)); - }, - onMouseClickRow: function(event) { - var element = event.element(); - if (this.isExpander(element)) { + if (this.isExpander(event.target)) { var row = event.findElement('tr'); if (this.hasChildren(row)) { - this.toggleBranch(row, element); + this.toggleBranch(row, event.target); } } }, @@ -31,7 +27,7 @@ }, isRow: function(element) { - return element.tagName && element.match('tr'); + return element && element.tagName && element.match('tr'); }, extractLevel: function(row) { @@ -46,105 +42,90 @@ getExpanderImageForRow: function(row) { return row.down('img'); - }, + }, + readExpandedCookie: function() { + var matches = document.cookie.match(/expanded_rows=(.+?);/); + this.expandedRows = matches ? matches[1].split(',') : []; + }, + saveExpandedCookie: function() { document.cookie = "expanded_rows=" + this.expandedRows.uniq().join(",") + "; path=/admin"; }, - - hideBranch: function(row, img) { - var level = this.extractLevel(row); - var sibling = row.next(); - while (sibling != null) { - if (this.isRow(sibling)) { - if (this.extractLevel(sibling) <= level) break; - sibling.hide(); - } - sibling = sibling.next(); - } + + persistCollapsed: function(row) { var pageId = this.extractPageId(row); - this.expandedRows = this.expandedRows.reject(function(row) { return row == pageId }); + this.expandedRows = this.expandedRows.without(pageId); this.saveExpandedCookie(); - if (img == null) img = this.getExpanderImageForRow(row); - img.src = img.src.replace(/collapse/, 'expand'); - row.removeClassName('children-visible'); - row.addClassName('children-hidden'); }, + + persistExpanded: function(row) { + this.expandedRows.push(this.extractPageId(row)); + this.saveExpandedCookie(); + }, + + toggleExpanded: function(row, img) { + if (!img) img = this.getExpanderImageForRow(row); + if (this.isExpanded(row)) { + img.src = img.src.replace('collapse', 'expand'); + row.removeClassName('children-visible'); + row.addClassName('children-hidden'); + this.persistCollapsed(row); + } else { + img.src = img.src.replace('expand', 'collapse'); + row.removeClassName('children-hidden'); + row.addClassName('children-visible'); + this.persistExpanded(row); + } + }, - showBranchInternal: function(row, img) { - var level = this.extractLevel(row); - var sibling = row.next(); - var children = false; - var childOwningSiblings = []; - while (sibling != null) { - if (this.isRow(sibling)) { - var siblingLevel = this.extractLevel(sibling); - if (siblingLevel <= level) break; - if (siblingLevel == level + 1) { - sibling.show(); - if(sibling.hasClassName('children-visible')) { - childOwningSiblings.push(sibling); - } else { - this.hideBranch(sibling); - } - } - children = true; - } - sibling = sibling.next(); + hideBranch: function(parent, img) { + var level = this.extractLevel(parent), row = parent.next(); + while (this.isRow(row) && this.extractLevel(row) > level) { + row.hide(); + row = row.next(); } - if (!children) this.getBranch(row); - if (img == null) img = this.getExpanderImageForRow(row); - img.src = img.src.replace(/expand/, 'collapse'); - childOwningSiblings.each(function(sib) { - this.showBranch(sib, null); - }, this); - row.removeClassName('children-hidden'); - row.addClassName('children-visible'); + this.toggleExpanded(parent, img); }, - showBranch: function(row, img) { - this.showBranchInternal(row, img); - this.expandedRows.push(this.extractPageId(row)); - this.saveExpandedCookie(); + showBranch: function(parent, img) { + var level = this.extractLevel(parent), row = parent.next(), + children = false, expandLevels = [level + 1]; + + while (this.isRow(row)) { + var currentLevel = this.extractLevel(row); + if (currentLevel <= level) break; + children = true; + if (currentLevel < expandLevels.last()) expandLevels.pop(); + if (expandLevels.include(currentLevel)) { + row.show(); + if (this.isExpanded(row)) expandLevels.push(currentLevel + 1); + } + row = row.next(); + } + if (!children) this.getBranch(parent); + this.toggleExpanded(parent, img); }, getBranch: function(row) { - var level = this.extractLevel(row).toString(); - var id = this.extractPageId(row).toString(); + var id = this.extractPageId(row), level = this.extractLevel(row), + spinner = $('busy-' + id); + new Ajax.Updater( row, '../admin/ui/pages/children/' + id + '/' + level, { - asynchronous: true, insertion: "after", - onLoading: function(request) { - $('busy-' + id).show(); - this.updating = true; - }.bind(this), - onComplete: function(request) { - var sibling = row.next(); - while (sibling != null) { - if (this.isRow(sibling)) { - var siblingLevel = this.extractLevel(sibling); - if (siblingLevel <= level) break; - this.setupRow(sibling); - } - sibling = sibling.nextSibling; - } - this.updating = false; - $('busy-' + id).fade(); - }.bind(this) + onLoading: function() { spinner.show(); this.updating = true }.bind(this), + onComplete: function() { spinner.fade(); this.updating = false }.bind(this) } ); }, toggleBranch: function(row, img) { if (!this.updating) { - if (this.isExpanded(row)) { - this.hideBranch(row, img); - } else { - this.showBranch(row, img); - } + var method = (this.isExpanded(row) ? 'hide' : 'show') + 'Branch'; + this[method](row, img); } } }); Index: /home/mislav/projects/radiant/public/javascripts/ruledtable.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/ruledtable.js (revision 573) +++ /home/mislav/projects/radiant/public/javascripts/ruledtable.js (working copy) @@ -1,19 +1,13 @@ var RuledTable = Class.create({ - initialize: function(element_id) { - var table = $(element_id).select('tr').each(this.setupRow, this) + initialize: function(element) { + if (Prototype.Browser.IE) + $(element). + observe('mouseover', this.onMouseOverRow.bindAsEventListener(this, 'addClassName')). + observe('mouseout', this.onMouseOverRow.bindAsEventListener(this, 'removeClassName')); }, - onMouseOverRow: function(event) { - this.addClassName('highlight'); - }, - - onMouseOutRow: function(event) { - this.removeClassName('highlight'); - }, - - setupRow: function(row) { - row.observe('mouseover', this.onMouseOverRow); - row.observe('mouseout', this.onMouseOutRow); - if (this.onRowSetup) this.onRowSetup(row); + onMouseOverRow: function(event, method) { + var row = event.findElement('tr'); + if (row) row[method]('highlight'); } }); Index: /home/mislav/projects/radiant/public/stylesheets/admin/main.css =================================================================== --- /home/mislav/projects/radiant/public/stylesheets/admin/main.css (revision 573) +++ /home/mislav/projects/radiant/public/stylesheets/admin/main.css (working copy) @@ -24,6 +24,9 @@ color: red; } +table { + border-collapse: collapse; +} /* main layout */ @@ -252,7 +255,8 @@ font-style: italic; font-weight: normal; } -#content table.index tr.highlight { +#content table.index tr.highlight, +#content table.index tr:hover { background-color: #ffffb3; } #content table.index .no-children .w1 { @@ -464,7 +468,7 @@ height: 280px; border: 1px solid #cdc295; font-family: Monaco, "Courier New", Courier, monospace; - font-size: 85%; + font-size: 95%; } #content #pages label { font-size: 85%; @@ -490,8 +494,10 @@ #popups .popup .close-link { font-size: 85%; } +#add-part-popup { + width: 17em; +} - /* tag reference */ #tag-reference-popup { Index: /home/mislav/projects/radiant/public/javascripts/admin.js =================================================================== --- /home/mislav/projects/radiant/public/javascripts/admin.js (revision 0) +++ /home/mislav/projects/radiant/public/javascripts/admin.js (revision 0) @@ -0,0 +1,89 @@ +document.observe('dom:loaded', function() { + when('site-map', function(table) { new SiteMap(table) }); + + when('page_title', function(title) { + var slug = $('page_slug'), + breadcrumb = $('page_breadcrumb'), + oldTitle = title.value; + + if (!slug || !breadcrumb) return; + + new Form.Element.Observer(title, 0.15, function() { + if (oldTitle.toSlug() == slug.value) slug.value = title.value.toSlug(); + if (oldTitle == breadcrumb.value) breadcrumb.value = title.value; + oldTitle = title.value; + }); + }); + + when($$('#pages div.part > input[type=hidden]:first-child'), function(parts) { + tabControl = new TabControl('tab-control'); + + parts.each(function(part, index) { + var page = part.up('.page'); + tabControl.addTab('tab-' + (index + 1), part.value, page.id); + }); + + tabControl.autoSelect(); + }); +}); + +// When object is available, do function fn. +function when(obj, fn) { + if (Object.isString(obj)) obj = /^[\w-]+$/.test(obj) ? $(obj) : $(document.body).down(obj); + if (Object.isArray(obj) && !obj.length) return; + if (obj) fn(obj); +} + +function part_added() { + var partNameField = $('part-name-field'); + var partIndexField = $('part-index-field'); + var index = parseInt(partIndexField.value) + 1; + var tab = 'tab-' + index; + var caption = partNameField.value; + var page = 'page-' + index; + tabControl.addTab(tab, caption, page); + Element.hide('add-part-popup'); + Element.hide('busy'); + partNameField.value = ''; + partIndexField.value = (index + 1).toString(); + $('add-part-button').disabled = false; + Field.focus(partNameField); + tabControl.select(tab); +} +function part_loading() { + $('add-part-button').disabled = true; + $('busy').appear(); +} +function valid_part_name() { + var partNameField = $('part-name-field'); + var name = partNameField.value.downcase().strip(); + var result = true; + if (name == '') { + alert('Part name cannot be empty.'); + return false; + } + tabControl.tabs.each(function(pair){ + if (tabControl.tabs.get(pair.key).caption == name) { + result = false; + alert('Part name must be unique.'); + throw $break; + } + }) + return result; +} +function center(element) { + var header = $('header') + element = $(element); + element.style.position = 'absolute'; + var dim = Element.getDimensions(element); + var top = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; + element.style.top = (top + 200) + 'px'; + element.style.left = ((header.offsetWidth - dim.width) / 2) + 'px'; +} +function toggle_add_part_popup() { + var popup = $('add-part-popup'); + var partNameField = $('part-name-field'); + center(popup); + Element.toggle(popup); + Field.focus(partNameField); +}
This paste will be private.
From the Design Piracy series on my blog: