diff --git a/app/controllers/admin/theme_assets_controller.rb b/app/controllers/admin/theme_assets_controller.rb index 2efa2a3d..80e00e61 100644 --- a/app/controllers/admin/theme_assets_controller.rb +++ b/app/controllers/admin/theme_assets_controller.rb @@ -7,6 +7,10 @@ module Admin assets = current_site.theme_assets.all @non_image_assets = assets.find_all { |a| a.stylesheet? || a.javascript? } @image_assets = assets.find_all { |a| a.image? } + + if request.xhr? + render :action => 'images', :layout => false + end end def new @@ -18,7 +22,17 @@ module Admin end def create - @asset = current_site.theme_assets.build(params[:theme_asset]) + # logger.debug "request = #{request.inspect}" + # logger.debug "file size = #{request.env['rack.input'].inspect}" + + # File.cp(request.env['rack.input'], '/Users/didier/Desktop/FOO') + + if params[:file] + # params[:theme_asset][:source] = request.env['rack.input'] + @asset = current_site.theme_assets.build(:source => params[:file]) + else + @asset = current_site.theme_assets.build(params[:theme_asset]) + end if @asset.save flash_success! diff --git a/app/models/theme_asset.rb b/app/models/theme_asset.rb index 1d462a2c..c488cc0a 100644 --- a/app/models/theme_asset.rb +++ b/app/models/theme_asset.rb @@ -64,6 +64,7 @@ class ThemeAsset def filename if not self.image? + # TODO: fix that for handling not image / stylesheets / javascripts assets "#{self.slug}.#{self.stylesheet? ? 'css' : 'js'}" else "#{self.slug}#{File.extname(self.source.file.original_filename)}" diff --git a/app/uploaders/asset_uploader.rb b/app/uploaders/asset_uploader.rb index aa230047..1adf706f 100644 --- a/app/uploaders/asset_uploader.rb +++ b/app/uploaders/asset_uploader.rb @@ -30,6 +30,8 @@ class AssetUploader < CarrierWave::Uploader::Base def set_content_type value = :other + content_type = File.mime_type?(original_filename) if file.content_type == 'application/octet-stream' + self.class.content_types.each_pair do |type, rules| rules.each do |rule| case rule diff --git a/app/uploaders/theme_asset_uploader.rb b/app/uploaders/theme_asset_uploader.rb index fcfd863a..437a4723 100644 --- a/app/uploaders/theme_asset_uploader.rb +++ b/app/uploaders/theme_asset_uploader.rb @@ -36,11 +36,13 @@ class ThemeAssetUploader < CarrierWave::Uploader::Base def set_content_type value = :other + content_type = File.mime_type?(original_filename) if file.content_type == 'application/octet-stream' + self.class.content_types.each_pair do |type, rules| rules.each do |rule| case rule - when String then value = type if file.content_type == rule - when Regexp then value = type if (file.content_type =~ rule) == 0 + when String then value = type if content_type == rule + when Regexp then value = type if (content_type =~ rule) == 0 end end end diff --git a/app/views/admin/shared/_head.html.haml b/app/views/admin/shared/_head.html.haml index 2043405b..f8d5fb61 100644 --- a/app/views/admin/shared/_head.html.haml +++ b/app/views/admin/shared/_head.html.haml @@ -6,7 +6,7 @@ = stylesheet_link_tag 'blueprint/screen', :media => 'screen' / [if IE] - = stylesheet_link_tag('blueprint/ie', :media => 'screen') + = stylesheet_link_tag 'blueprint/ie', :media => 'screen' = stylesheet_link_tag 'admin/layout', 'admin/plugins/toggle', 'admin/menu', 'admin/buttons', 'admin/formtastic', 'admin/formtastic_changes', 'admin/application', :media => 'screen', :cache => Rails.env.production? diff --git a/app/views/admin/theme_assets/_asset.html.haml b/app/views/admin/theme_assets/_asset.html.haml index 0d21bdd1..95f5047c 100644 --- a/app/views/admin/theme_assets/_asset.html.haml +++ b/app/views/admin/theme_assets/_asset.html.haml @@ -1,7 +1,11 @@ -%li{ :class => "asset #{'last' if (asset_counter + 1) % 6 == 0}"} - %h4= link_to truncate(asset.slug, :length => 22), edit_admin_theme_asset_path(asset) +- per_row ||= 6 +- edit_mode = defined?(edit).nil? ? true: edit + +%li{ :class => "asset #{'last' if (asset_counter + 1) % per_row == 0}"} + %h4= link_to truncate(asset.slug, :length => 22), edit_mode ? edit_admin_theme_asset_path(asset) : asset.source.url .image .inside = vignette_tag(asset) - .actions - = link_to image_tag('admin/list/icons/cross.png'), admin_theme_asset_path(asset), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete \ No newline at end of file + - if edit_mode + .actions + = link_to image_tag('admin/list/icons/cross.png'), admin_theme_asset_path(asset), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete \ No newline at end of file diff --git a/app/views/admin/theme_assets/_form.html.haml b/app/views/admin/theme_assets/_form.html.haml index 23f3e659..b289d20a 100644 --- a/app/views/admin/theme_assets/_form.html.haml +++ b/app/views/admin/theme_assets/_form.html.haml @@ -1,5 +1,6 @@ - content_for :head do - = javascript_include_tag 'admin/plugins/codemirror/codemirror', 'admin/theme_assets.js' + = javascript_include_tag 'admin/plugins/codemirror/codemirror', 'admin/plugins/fancybox', 'admin/plugins/plupload/plupload.full.js', 'admin/theme_assets.js' + = stylesheet_link_tag 'admin/plugins/fancybox', 'admin/box' = f.hidden_field :performing_plain_text @@ -22,12 +23,14 @@ = f.select :content_type, ["stylesheet", "javascript"] = f.custom_input :plain_text, :css => 'full', :with_label => false do - %code{ :class => (@asset.new_record? || (@asset.size && @asset.size > 40000) ? 'nude' : @asset.content_type) } + %code{ :class => (@asset.size && @asset.size > 40000 ? 'nude' : (@asset.content_type || 'stylesheet')) } = f.text_area :plain_text + %li.more + = link_to t('.picker_link'), admin_theme_assets_path, :id => 'asset-picker-link' %span.alt = t('admin.theme_assets.form.choose_file') - + - if @asset.image? = f.foldable_inputs :name => "#{t('formtastic.titles.preview')} #{image_dimensions_and_size(@asset)}", :class => 'preview' do %li diff --git a/app/views/admin/theme_assets/images.html.haml b/app/views/admin/theme_assets/images.html.haml new file mode 100644 index 00000000..2371c1af --- /dev/null +++ b/app/views/admin/theme_assets/images.html.haml @@ -0,0 +1,12 @@ +#theme-images.asset-picker + %h2= t('.title') + + .actions + = admin_button_tag t('admin.theme_assets.index.new'), admin_theme_assets_url(:json), :class => 'button small add', :id => 'upload-link' + + - if @image_assets.empty? + %p.no-items= t('.no_items') + - else + %ul.assets + = render :partial => 'asset', :collection => @image_assets, :locals => { :per_row => 3, :edit => false } + %li.clear \ No newline at end of file diff --git a/config/initializers/mongoid.rb b/config/initializers/mongoid.rb index 8144f097..c69f778d 100644 --- a/config/initializers/mongoid.rb +++ b/config/initializers/mongoid.rb @@ -29,7 +29,7 @@ module Mongoid #:nodoc: end end - Rails.logger.debug "conditions = #{conditions.inspect} / #{options[:scope].inspect}" + # Rails.logger.debug "conditions = #{conditions.inspect} / #{options[:scope].inspect}" return if document.class.where(conditions).empty? diff --git a/doc/TODO b/doc/TODO index baa05e8f..b2fcf22e 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,16 +1,21 @@ BOARD: -- theme assets - theme assets picker (???) - -- assets uploader: remove old files if new one + x lightbox (http://fancybox.net/api) + x select it + - flash upload (http://www.plupload.com/example_custom.php) - theme assets: disable version if not image +- refactor theme assets / assets uploaders BACKLOG: - devise messages in French - localize devise emails + +- cucumber features for admin pages - refactoring admin crud (pages + layouts + snippets) +- icons for mime type + - new types for custom field - file - boolean @@ -18,11 +23,14 @@ BACKLOG: - refactoring: CustomFields::CustomField => CustomFields::Field - optimization custom_fields: use dynamic class for a collection instead of modifying the metaclass each time we build an item +- deploy on Heroku + BUGS: - when assigning new layout, disabled parts show up :-( (js problem) NICE TO HAVE: - asset collections: custom resizing if image +- super_finder DONE: x admin layout @@ -91,4 +99,6 @@ x liquid rendering engine x contents pagination x how to disable a page part in layout ? (BUG) x non published page (redirect to 404 ?) -x refactoring page.rb => create module pagetree \ No newline at end of file +x refactoring page.rb => create module pagetree +! assets uploader: remove old files if new one (BUG non ) +x CodeMirror: switch js -> css -> js .... (http://marijn.haverbeke.nl/codemirror/manual.html) \ No newline at end of file diff --git a/lib/locomotive.rb b/lib/locomotive.rb index 8b8e0b01..e9bea03f 100644 --- a/lib/locomotive.rb +++ b/lib/locomotive.rb @@ -3,6 +3,7 @@ require 'locomotive/configuration' require 'locomotive/liquid' require 'locomotive/mongoid' + module Locomotive class << self diff --git a/lib/locomotive/mongoid.rb b/lib/locomotive/mongoid.rb index 3402c827..65ef9d20 100644 --- a/lib/locomotive/mongoid.rb +++ b/lib/locomotive/mongoid.rb @@ -1 +1,2 @@ -require 'locomotive/mongoid/document' \ No newline at end of file +require 'locomotive/mongoid/document' +require 'locomotive/mongoid/model_extensions' \ No newline at end of file diff --git a/public/images/admin/plugins/fancybox/blank.gif b/public/images/admin/plugins/fancybox/blank.gif new file mode 100755 index 00000000..35d42e80 Binary files /dev/null and b/public/images/admin/plugins/fancybox/blank.gif differ diff --git a/public/images/admin/plugins/fancybox/fancy_close.png b/public/images/admin/plugins/fancybox/fancy_close.png new file mode 100755 index 00000000..07035307 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_close.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_loading.png b/public/images/admin/plugins/fancybox/fancy_loading.png new file mode 100755 index 00000000..25030179 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_loading.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_nav_left.png b/public/images/admin/plugins/fancybox/fancy_nav_left.png new file mode 100755 index 00000000..ebaa6a4f Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_nav_left.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_nav_right.png b/public/images/admin/plugins/fancybox/fancy_nav_right.png new file mode 100755 index 00000000..873294e9 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_nav_right.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_e.png b/public/images/admin/plugins/fancybox/fancy_shadow_e.png new file mode 100755 index 00000000..2eda0893 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_e.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_n.png b/public/images/admin/plugins/fancybox/fancy_shadow_n.png new file mode 100755 index 00000000..69aa10e2 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_n.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_ne.png b/public/images/admin/plugins/fancybox/fancy_shadow_ne.png new file mode 100755 index 00000000..79f6980a Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_ne.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_nw.png b/public/images/admin/plugins/fancybox/fancy_shadow_nw.png new file mode 100755 index 00000000..7182cd93 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_nw.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_s.png b/public/images/admin/plugins/fancybox/fancy_shadow_s.png new file mode 100755 index 00000000..d8858bfb Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_s.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_se.png b/public/images/admin/plugins/fancybox/fancy_shadow_se.png new file mode 100755 index 00000000..541e3ffd Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_se.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_sw.png b/public/images/admin/plugins/fancybox/fancy_shadow_sw.png new file mode 100755 index 00000000..b451689f Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_sw.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_shadow_w.png b/public/images/admin/plugins/fancybox/fancy_shadow_w.png new file mode 100755 index 00000000..8a4e4a88 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_shadow_w.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_title_left.png b/public/images/admin/plugins/fancybox/fancy_title_left.png new file mode 100755 index 00000000..6049223d Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_title_left.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_title_main.png b/public/images/admin/plugins/fancybox/fancy_title_main.png new file mode 100755 index 00000000..8044271f Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_title_main.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_title_over.png b/public/images/admin/plugins/fancybox/fancy_title_over.png new file mode 100755 index 00000000..d9f458f4 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_title_over.png differ diff --git a/public/images/admin/plugins/fancybox/fancy_title_right.png b/public/images/admin/plugins/fancybox/fancy_title_right.png new file mode 100755 index 00000000..e36d9db2 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancy_title_right.png differ diff --git a/public/images/admin/plugins/fancybox/fancybox-x.png b/public/images/admin/plugins/fancybox/fancybox-x.png new file mode 100755 index 00000000..c2130f86 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancybox-x.png differ diff --git a/public/images/admin/plugins/fancybox/fancybox-y.png b/public/images/admin/plugins/fancybox/fancybox-y.png new file mode 100755 index 00000000..7ef399b9 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancybox-y.png differ diff --git a/public/images/admin/plugins/fancybox/fancybox.png b/public/images/admin/plugins/fancybox/fancybox.png new file mode 100755 index 00000000..65e14f68 Binary files /dev/null and b/public/images/admin/plugins/fancybox/fancybox.png differ diff --git a/public/javascripts/admin/application.js b/public/javascripts/admin/application.js index 2bc5faca..08bee1cd 100644 --- a/public/javascripts/admin/application.js +++ b/public/javascripts/admin/application.js @@ -21,12 +21,15 @@ $.growl.settings.dockCss = { var addCodeMirrorEditor = function(type, el, parser) { var parserfile = "parse" + type + ".js"; if (parser != undefined) parserfile = parser; - if (type == 'liquid') type = 'xml'; + // if (type == 'liquid') type = 'xml'; var editor = CodeMirror.fromTextArea(el.attr('id'), { height: "400px", parserfile: parserfile, - stylesheet: ["/stylesheets/admin/plugins/codemirror/" + type + "colors.css", "/stylesheets/admin/plugins/codemirror/liquidcolors.css"], + stylesheet: [ + "/stylesheets/admin/plugins/codemirror/csscolors.css", + "/stylesheets/admin/plugins/codemirror/javascriptcolors.css", + "/stylesheets/admin/plugins/codemirror/liquidcolors.css"], path: "/javascripts/admin/plugins/codemirror/", continuousScanning: 500, reindentOnLoad: true, diff --git a/public/javascripts/admin/plugins/codemirror/codemirror.js b/public/javascripts/admin/plugins/codemirror/codemirror.js index 97e2657b..f4de2207 100644 --- a/public/javascripts/admin/plugins/codemirror/codemirror.js +++ b/public/javascripts/admin/plugins/codemirror/codemirror.js @@ -33,6 +33,8 @@ var CodeMirror = (function(){ iframeClass: null, passDelay: 200, passTime: 50, + lineNumberDelay: 200, + lineNumberTime: 50, continuousScanning: false, saveFunction: null, onChange: null, @@ -41,7 +43,7 @@ var CodeMirror = (function(){ disableSpellcheck: true, textWrapping: true, readOnly: false, - width: "100%", + width: "", height: "300px", autoMatchParens: false, parserConfig: null, @@ -50,67 +52,49 @@ var CodeMirror = (function(){ activeTokens: null, cursorActivity: null, lineNumbers: false, - indentUnit: 2 + indentUnit: 2, + domain: null }); - function wrapLineNumberDiv(place) { - return function(node) { - var container = document.createElement("DIV"), - nums = document.createElement("DIV"), - scroller = document.createElement("DIV"); - container.style.position = "relative"; - nums.style.position = "absolute"; - nums.style.height = "100%"; - if (nums.style.setExpression) { - try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} - catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions - } - nums.style.top = "0px"; - nums.style.overflow = "hidden"; - place(container); - container.appendChild(node); - container.appendChild(nums); - scroller.className = "CodeMirror-line-numbers"; - nums.appendChild(scroller); + function addLineNumberDiv(container) { + var nums = document.createElement("DIV"), + scroller = document.createElement("DIV"); + nums.style.position = "absolute"; + nums.style.height = "100%"; + if (nums.style.setExpression) { + try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} + catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions } + nums.style.top = "0px"; + nums.style.overflow = "hidden"; + container.appendChild(nums); + scroller.className = "CodeMirror-line-numbers"; + nums.appendChild(scroller); + return nums; } - function applyLineNumbers(frame) { - var win = frame.contentWindow, doc = win.document, - nums = frame.nextSibling, scroller = nums.firstChild; + function frameHTML(options) { + if (typeof options.parserfile == "string") + options.parserfile = [options.parserfile]; + if (typeof options.stylesheet == "string") + options.stylesheet = [options.stylesheet]; - var nextNum = 1, barWidth = null; - function sizeBar() { - if (!frame.offsetWidth || !win.Editor) { - for (var cur = frame; cur.parentNode; cur = cur.parentNode) { - if (cur != document) { - clearInterval(sizeInterval); - return; - } - } - } - - if (nums.offsetWidth != barWidth) { - barWidth = nums.offsetWidth; - nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px"); - } - } - function update() { - var diff = 20 + Math.max(doc.body.offsetHeight, frame.offsetHeight) - scroller.offsetHeight; - for (var n = Math.ceil(diff / 10); n > 0; n--) { - var div = document.createElement("DIV"); - div.appendChild(document.createTextNode(nextNum++)); - scroller.appendChild(div); - } - nums.scrollTop = doc.body.scrollTop || doc.documentElement.scrollTop || 0; - } - sizeBar(); - update(); - win.addEventHandler(win, "scroll", update); - win.addEventHandler(win, "resize", update); - var sizeInterval = setInterval(sizeBar, 500); + var html = ["
"]; + // Hack to work around a bunch of IE8-specific problems. + html.push(""); + forEach(options.stylesheet, function(file) { + html.push(""); + }); + forEach(options.basefiles.concat(options.parserfile), function(file) { + html.push(""); - }); - html.push(""); - - var doc = this.win.document; - doc.open(); - doc.write(html.join("")); - doc.close(); + if (!options.domain || !internetExplorer) { + this.win.document.open(); + this.win.document.write(frameHTML(options)); + this.win.document.close(); + } } CodeMirror.prototype = { init: function() { if (this.options.initCallback) this.options.initCallback(this); - if (this.options.lineNumbers) applyLineNumbers(this.frame); + if (this.options.lineNumbers) this.activateLineNumbers(); if (this.options.reindentOnLoad) this.reindent(); }, getCode: function() {return this.editor.getCode();}, setCode: function(code) {this.editor.importCode(code);}, - selection: function() {return this.editor.selectedText();}, + selection: function() {this.focusIfIE(); return this.editor.selectedText();}, reindent: function() {this.editor.reindent();}, - reindentSelection: function() {this.editor.reindentSelection(null);}, + reindentSelection: function() {this.focusIfIE(); this.editor.reindentSelection(null);}, + focusIfIE: function() { + // in IE, a lot of selection-related functionality only works when the frame is focused + if (this.win.select.ie_selection) this.focus(); + }, focus: function() { this.win.focus(); if (this.editor.selectionSnapshot) // IE hack - this.win.select.selectCoords(this.win, this.editor.selectionSnapshot); + this.win.select.setBookmark(this.win.document.body, this.editor.selectionSnapshot); }, replaceSelection: function(text) { this.focus(); @@ -192,8 +182,8 @@ var CodeMirror = (function(){ replaceChars: function(text, start, end) { this.editor.replaceChars(text, start, end); }, - getSearchCursor: function(string, fromCursor) { - return this.editor.getSearchCursor(string, fromCursor); + getSearchCursor: function(string, fromCursor, caseFold) { + return this.editor.getSearchCursor(string, fromCursor, caseFold); }, undo: function() {this.editor.history.undo();}, @@ -204,18 +194,76 @@ var CodeMirror = (function(){ grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);}, ungrabKeys: function() {this.editor.ungrabKeys();}, - setParser: function(name) {this.editor.setParser(name);}, - - cursorPosition: function(start) { - if (this.win.select.ie_selection) this.focus(); - return this.editor.cursorPosition(start); + setParser: function(name) { this.editor.setParser(name); }, + setSpellcheck: function(on) {this.win.document.body.spellcheck = on;}, + setStylesheet: function(names) { + if (typeof names === "string") names = [names]; + var activeStylesheets = {}; + var matchedNames = {}; + var links = this.win.document.getElementsByTagName("link"); + // Create hashes of active stylesheets and matched names. + // This is O(n^2) but n is expected to be very small. + for (var x = 0, link; link = links[x]; x++) { + if (link.rel.indexOf("stylesheet") !== -1) { + for (var y = 0; y < names.length; y++) { + var name = names[y]; + if (link.href.substring(link.href.length - name.length) === name) { + activeStylesheets[link.href] = true; + matchedNames[name] = true; + } + } + } + } + // Activate the selected stylesheets and disable the rest. + for (var x = 0, link; link = links[x]; x++) { + if (link.rel.indexOf("stylesheet") !== -1) { + link.disabled = !(link.href in activeStylesheets); + } + } + // Create any new stylesheets. + for (var y = 0; y < names.length; y++) { + var name = names[y]; + if (!(name in matchedNames)) { + var link = this.win.document.createElement("link"); + link.rel = "stylesheet"; + link.type = "text/css"; + link.href = name; + this.win.document.getElementsByTagName('head')[0].appendChild(link); + } + } }, + setTextWrapping: function(on) { + if (on == this.options.textWrapping) return; + this.win.document.body.style.whiteSpace = on ? "" : "nowrap"; + this.options.textWrapping = on; + if (this.lineNumbers) { + this.setLineNumbers(false); + this.setLineNumbers(true); + } + }, + setIndentUnit: function(unit) {this.win.indentUnit = unit;}, + setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;}, + setTabMode: function(mode) {this.options.tabMode = mode;}, + setLineNumbers: function(on) { + if (on && !this.lineNumbers) { + this.lineNumbers = addLineNumberDiv(this.wrapping); + this.activateLineNumbers(); + } + else if (!on && this.lineNumbers) { + this.wrapping.removeChild(this.lineNumbers); + this.wrapping.style.marginLeft = ""; + this.lineNumbers = null; + } + }, + + cursorPosition: function(start) {this.focusIfIE(); return this.editor.cursorPosition(start);}, firstLine: function() {return this.editor.firstLine();}, lastLine: function() {return this.editor.lastLine();}, nextLine: function(line) {return this.editor.nextLine(line);}, prevLine: function(line) {return this.editor.prevLine(line);}, lineContent: function(line) {return this.editor.lineContent(line);}, setLineContent: function(line, content) {this.editor.setLineContent(line, content);}, + removeLine: function(line){this.editor.removeLine(line);}, insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);}, selectLines: function(startLine, startOffset, endLine, endOffset) { this.win.focus(); @@ -235,14 +283,125 @@ var CodeMirror = (function(){ } return num; }, - - // Old number-based line interface - jumpToLine: function(n) { - this.selectLines(this.nthLine(n), 0); + jumpToLine: function(line) { + if (typeof line == "number") line = this.nthLine(line); + this.selectLines(line, 0); this.win.focus(); }, - currentLine: function() { - return this.lineNumber(this.cursorPosition().line); + currentLine: function() { // Deprecated, but still there for backward compatibility + return this.lineNumber(this.cursorLine()); + }, + cursorLine: function() { + return this.cursorPosition().line; + }, + + activateLineNumbers: function() { + var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body, + nums = this.lineNumbers, scroller = nums.firstChild, self = this; + var barWidth = null; + + function sizeBar() { + if (frame.offsetWidth == 0) return; + for (var root = frame; root.parentNode; root = root.parentNode); + if (!nums.parentNode || root != document || !win.Editor) { + // Clear event handlers (their nodes might already be collected, so try/catch) + try{clear();}catch(e){} + clearInterval(sizeInterval); + return; + } + + if (nums.offsetWidth != barWidth) { + barWidth = nums.offsetWidth; + nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px"); + } + } + function doScroll() { + nums.scrollTop = body.scrollTop || doc.documentElement.scrollTop || 0; + } + // Cleanup function, registered by nonWrapping and wrapping. + var clear = function(){}; + sizeBar(); + var sizeInterval = setInterval(sizeBar, 500); + + function nonWrapping() { + var nextNum = 1, pending; + function update() { + var target = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)); + var endTime = new Date().getTime() + self.options.lineNumberTime; + while (scroller.offsetHeight < target && (!scroller.firstChild || scroller.offsetHeight)) { + scroller.appendChild(document.createElement("DIV")); + scroller.lastChild.innerHTML = nextNum++; + if (new Date().getTime() > endTime) { + if (pending) clearTimeout(pending); + pending = setTimeout(update, self.options.lineNumberDelay); + break; + } + } + doScroll(); + } + var onScroll = win.addEventHandler(win, "scroll", update, true), + onResize = win.addEventHandler(win, "resize", update, true); + clear = function(){onScroll(); onResize(); if (pending) clearTimeout(pending);}; + update(); + } + function wrapping() { + var node, lineNum, next, pos; + + function addNum(n) { + if (!lineNum) lineNum = scroller.appendChild(document.createElement("DIV")); + lineNum.innerHTML = n; + pos = lineNum.offsetHeight + lineNum.offsetTop; + lineNum = lineNum.nextSibling; + } + function work() { + if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return; + + var endTime = new Date().getTime() + self.options.lineNumberTime; + while (node) { + addNum(next++); + for (; node && !win.isBR(node); node = node.nextSibling) { + var bott = node.offsetTop + node.offsetHeight; + while (scroller.offsetHeight && bott - 3 > pos) addNum(" "); + } + if (node) node = node.nextSibling; + if (new Date().getTime() > endTime) { + pending = setTimeout(work, self.options.lineNumberDelay); + return; + } + } + // While there are un-processed number DIVs, or the scroller is smaller than the frame... + var target = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)); + while (lineNum || (scroller.offsetHeight < target && (!scroller.firstChild || scroller.offsetHeight))) + addNum(next++); + doScroll(); + } + function start() { + doScroll(); + node = body.firstChild; + lineNum = scroller.firstChild; + pos = 0; + next = 1; + work(); + } + + start(); + var pending = null; + function update() { + if (pending) clearTimeout(pending); + if (self.editor.allClean()) start(); + else pending = setTimeout(update, 200); + } + self.updateNumbers = update; + var onScroll = win.addEventHandler(win, "scroll", doScroll, true), + onResize = win.addEventHandler(win, "resize", update, true); + clear = function(){ + if (pending) clearTimeout(pending); + if (self.updateNumbers == update) self.updateNumbers = null; + onScroll(); + onResize(); + }; + } + (this.options.textWrapping ? wrapping : nonWrapping)(); } }; diff --git a/public/javascripts/admin/plugins/codemirror/editor.js b/public/javascripts/admin/plugins/codemirror/editor.js index 58b1d4fe..39677793 100644 --- a/public/javascripts/admin/plugins/codemirror/editor.js +++ b/public/javascripts/admin/plugins/codemirror/editor.js @@ -4,6 +4,11 @@ * plain sequences of andThe requested content cannot be loaded.
Please try again later.
3){h.pop()}while(h.length<4){h.push(0)}i=o.split(".");while(i.length>4){i.pop()}do{q=parseInt(i[m],10);j=parseInt(h[m],10);m++}while(m