OSDN Git Service

t#32246:add sheet
authoryasushiito <yas@pen-chan.jp>
Sat, 19 Oct 2013 07:54:58 +0000 (16:54 +0900)
committeryasushiito <yas@pen-chan.jp>
Sat, 19 Oct 2013 07:54:58 +0000 (16:54 +0900)
25 files changed:
app/assets/javascripts/application.js
app/assets/javascripts/pettanr_sheeter.js.coffee [new file with mode: 0644]
app/assets/javascripts/sheets.js.coffee
app/controllers/sheets_controller.rb
app/models/sheet.rb
app/models/sheet_panel.rb
app/views/sheet_panels/_element.html.erb [new file with mode: 0644]
app/views/sheet_panels/_element_face.html.erb [new file with mode: 0644]
app/views/sheet_panels/_form.html.erb
app/views/sheet_panels/_play_header.html.erb
app/views/sheet_panels/_scenario.html.erb [new file with mode: 0644]
app/views/sheet_panels/edit.html.erb
app/views/sheet_panels/new.html.erb
app/views/sheets/_body.html.erb
app/views/sheets/_element_tab.html.erb [new file with mode: 0644]
app/views/sheets/_form.html.erb
app/views/sheets/_standard.html.erb
app/views/sheets/edit.html.erb
app/views/sheets/new.html.erb
app/views/sheets/play.html.erb
app/views/sheets/show.html.erb
config/locales/pettanr.ja.yml
spec/controllers/sheets_controller_spec.rb
spec/models/sheet_panel_spec.rb
spec/models/sheet_spec.rb

index 26e94c0..ce8c00b 100644 (file)
@@ -9,8 +9,10 @@
 //= require jquery.ui.all
 //= require textchange
 //= require pettanr_editor
+//= require pettanr_sheeter
 //= require writing_formats
 //= require_directory ./helpers
 //= require speech_balloon_templates
 //= require panels
+//= require sheets
 //  require_tree .
diff --git a/app/assets/javascripts/pettanr_sheeter.js.coffee b/app/assets/javascripts/pettanr_sheeter.js.coffee
new file mode 100644 (file)
index 0000000..51afc3d
--- /dev/null
@@ -0,0 +1,89 @@
+class PettanrSheeter\r
+  @pettanr_current_sheet_id = 0\r
+  \r
+  @new_element_index = {}\r
+  @new_element_index[PettanrSheeter.pettanr_current_sheet_id] = 0\r
+  \r
+  @current_sheet = () ->\r
+    $('#sheet' + PettanrSheeter.pettanr_current_sheet_id.toString())\r
+  \r
+  @set_tree_value = (keys, last_attr, value) ->\r
+    key = keys.shift()\r
+    if keys.length <= 0\r
+      last_attr[key] = value\r
+    else\r
+      last_attr[key] = last_attr[key] || {}\r
+      PettanrSheeter.set_tree_value(keys, last_attr[key], value)\r
+\r
+  @is_editting = () ->\r
+    trace = '#sheet' + PettanrSheeter.pettanr_current_sheet_id.toString() + 'wrapper'\r
+    if $(trace) and $(trace).attr('editable')\r
+      return true\r
+    else\r
+      return false\r
+  @is_editable = (p) ->\r
+    if p.parent().attr('editable')\r
+      return true\r
+    else\r
+      return false\r
+  @is_var = (o) ->\r
+    if parseInt(o.attr('no_attr')) > 0\r
+      return false\r
+    else\r
+      if o.attr('column') \r
+        if o.attr('column') == '_destroy' and o.val().length < 1\r
+          return false\r
+        else\r
+          return true\r
+      else\r
+        return false\r
+  @is_element = (o) ->\r
+    if o.attr('element_type')\r
+      return true\r
+    else\r
+      return false\r
+  @is_element_part = (o) ->\r
+    if o.attr('element_part_type')\r
+      return true\r
+    else\r
+      return false\r
+  @element_is = (element_type, o) ->\r
+    if PettanrSheeter.is_element(o) and o.attr('element_type') == element_type\r
+      return true\r
+    else\r
+      return false\r
+  @element_types  = {'sheet_panel': 'sheet_panels'}\r
+  @element_type_to_table = (element_type) ->\r
+    PettanrSheeter.element_types[element_type]\r
+\r
+  @make_tree = (attr, o) ->\r
+    if PettanrSheeter.is_var(o)\r
+      tree = 'sheets-' + o.attr('sheet_id') + '-'\r
+      if PettanrSheeter.is_element(o)\r
+        tree = tree + PettanrSheeter.element_type_to_table(o.attr('element_type')) + '_attributes-' + o.attr('element_id') + '-'\r
+        if PettanrSheeter.is_element_part(o)\r
+          tree = tree + o.attr('element_part_type') + '_attributes-'\r
+      tree = tree + o.attr('column')\r
+      keys = tree.split('-')\r
+      PettanrSheeter.set_tree_value(keys, attr, o.val())\r
+  \r
+  @sheet_tag_id = (element) ->\r
+    '#sheet' + element.attr('sheet_id')\r
+  \r
+  @element_tag_id = (element) ->\r
+    '#sheet' + element.attr('sheet_id') + element.attr('element_type') + element.attr('element_id')\r
+  \r
+  @element_part_tag_id = (element_part) ->\r
+    '#sheet' + element_part.attr('sheet_id') + element_part.attr('element_type') + element_part.attr('element_id') + element_part.attr('element_part_type') + element_part.attr('element_part_id')\r
+  \r
+  @refresh_attribute = (field) ->\r
+    attr = {}\r
+    $('input').map ->\r
+      PettanrSheeter.make_tree(attr, $(@))\r
+    $('textarea').map  ->\r
+      PettanrSheeter.make_tree(attr, $(@))\r
+    $('select').map ->\r
+      PettanrSheeter.make_tree(attr, $(@))\r
+    field.val(JSON.stringify(attr['sheets'][PettanrSheeter.pettanr_current_sheet_id.toString() ]))\r
+  \r
+@PettanrSheeter = PettanrSheeter\r
index 634a64f..c9ebf21 100644 (file)
@@ -1,11 +1,11 @@
 $ ->
   confirm_confirm_confirm = () ->
     confirm(  )
-  editor = window.PettanrEditor
+  editor = window.PettanrSheeter
   
-  $('.panel-editor').map ->
+  $('.sheet-editor').map ->
     if $(@).attr('current') and parseInt($(@).attr('current')) > 0
-      editor.pettanr_current_panel_id = parseInt($(@).attr('panel_id'))
+      editor.pettanr_current_sheet_id = parseInt($(@).attr('sheet_id'))
   if editor.is_editting()
     $('#tabs').tabs()
     $('#elements-tabs').tabs()
@@ -17,12 +17,9 @@ $ ->
     $("#elements-tabs li").map ->
       $(@).mouseover -> 
         switch $(@).attr('element_type')
-          when 'speech_balloon'
+          when 'sheet_panel'
             trace = editor.element_tag_id($(@)) 
-            t = $('img', $(trace))
-          when 'panel_picture'
-            trace = editor.element_tag_id($(@)) + 'img'
-            t = $(trace)
+            t = $('.pettanr-comic-panel', $(trace))
           else
             t = null
         if t
@@ -30,12 +27,9 @@ $ ->
             $(@).css('display', 'block')
       $(@).mouseout -> 
         switch $(@).attr('element_type')
-          when 'speech_balloon'
+          when 'sheet_panel'
             trace = editor.element_tag_id($(@)) 
-            t = $('img', $(trace))
-          when 'panel_picture'
-            trace = editor.element_tag_id($(@)) + 'img'
-            t = $(trace)
+            t = $('.pettanr-comic-panel', $(trace))
           else
             t = null
         if t
@@ -55,9 +49,9 @@ $ ->
         if confirm('destroy ?')
           trace = editor.element_tag_id($(@))
           $(trace + '_destroy').val('true')
-          panel_trace = editor.panel_tag_id($(@))
-          update_t(panel_trace + 'tsort')
-          update_z(panel_trace + 'zsort')
+          sheet_trace = editor.panel_tag_id($(@))
+          update_t(sheet_trace + 'tsort')
+          update_z(sheet_trace + 'zsort')
           # sync
           $(trace + 'element_tab').css('display', 'none')
           $(trace + 'tab_panel').css('display', 'none')
@@ -69,25 +63,19 @@ $ ->
           $(trace).css('display', 'none')
           
     
-    $('#pettanr-panel-submit').focusin ->
-      editor.refresh_attribute($('#pettanr-panel-json'))
+    $('#pettanr-sheet-submit').focusin ->
+      editor.refresh_attribute($('#pettanr-sheet-json'))
     
-    # panel
-    $('.pettanr-comic-panel').map ->
+    # sheet
+    $('.sheet').map ->
       if editor.is_editable($(@))
         $(@).resizable {
           stop: ( event, ui ) ->
-            trace = editor.panel_tag_id($(@))
+            trace = editor.sheet_tag_id($(@))
             w = parseInt($(@).width())
             h = parseInt($(@).height())
             $(trace + 'width').val(w)
             $(trace + 'height').val(h)
-            $('.pettanr-comic-ground-picture').map ->
-              $(@).width(w)
-              $(@).height(h)
-            $('.pettanr-comic-ground-color').map ->
-              $(@).width(w)
-              $(@).height(h)
           , autoHide: true
         }
     
@@ -95,168 +83,30 @@ $ ->
     $('input').map  ->
       if $(@).attr('element_type')
       else
-        if $(@).attr('panel_id')
+        if $(@).attr('sheet_id')
           $(@).focusout ->
             switch $(@).attr('column')
               when 'width'
-                trace = editor.panel_tag_id($(@))
+                trace = editor.sheet_tag_id($(@))
                 $(trace).width(parseInt( $(@).val()))
               when 'height'
-                trace = editor.panel_tag_id($(@))
+                trace = editor.sheet_tag_id($(@))
                 $(trace).height(parseInt( $(@).val()))
-              when 'border'
-                trace = editor.panel_tag_id($(@))
-                $(trace).css('border-width', parseInt($(@).val()).toString() + 'px')
     
-    # panel picture
-    PictureSizeHelper.add_helper()
-    
-    $('.pettanr-panel-picture-wrapper').map ->
+    $('.sheet_panel').map ->
       $(@).draggable {
         stop: ( event, ui ) ->
           trace = editor.element_tag_id($(@))
-          img = $(trace + 'img')
-          left = img.parent().position().left + $(@).position().left
-          top = img.parent().position().top + $(@).position().top
-          $(trace + 'x').val(parseInt(left))
-          $(trace + 'y').val(parseInt(top))
-      }
-    
-    $('.panel-picture').map ->
-      $(@).resizable {
-        stop: ( event, ui ) ->
-          resize_div = $(@)
-          panel_picture_div = resize_div.parent()
-          trace = editor.element_tag_id(panel_picture_div)
-          
-          resize_div.css('top', '0px')
-          resize_div.css('left', '0px')
-          if ui.originalPosition.top != ui.position.top
-            t = panel_picture_div.position().top + ui.position.top
-            $(trace + 'y').val(Math.floor(t))
-            panel_picture_div.css('top', t.toString() + 'px')
-          if ui.originalPosition.left != ui.position.left
-            l = panel_picture_div.position().left + ui.position.left
-            $(trace + 'x').val(Math.floor(l))
-            panel_picture_div.css('left', l.toString() + 'px')
-          w = if $(trace + 'width').val() < 0
-            -ui.size.width
-          else
-            ui.size.width
-          h = if $(trace + 'height').val() < 0
-            -ui.size.height
-          else
-            ui.size.height
-          $(trace + 'width').val(w)
-          $(trace + 'height').val(h)
-        resize: ( event, ui ) ->
-          resize_div = $(@)
-          panel_picture_div = resize_div.parent()
-          trace = editor.element_tag_id(panel_picture_div)
-        handles: 'all',
-        autoHide: true
-      }
-    
-    # sync view 
-    $('input').map  ->
-      if editor.element_is('panel_picture', $(@))
-        $(@).focusout ->
-          switch $(@).attr('column')
-            when 'x'
-              trace = editor.element_tag_id($(@)) + 'div'
-              v = parseInt($(@).val()).toString() + 'px'
-              $(trace).css('left', v)
-            when 'y'
-              trace = editor.element_tag_id($(@)) + 'div'
-              v = parseInt($(@).val()).toString() + 'px'
-              $(trace).css('top', v)
-            when 'width'
-              trace = editor.element_tag_id($(@)) + 'img'
-              w = parseInt($(@).val())
-              $(trace).width(Math.abs(w))
-              $(trace).parent().width(Math.abs(w))
-              h = parseInt($(editor.element_tag_id($(@)) + 'height').val())
-            when 'height'
-              trace = editor.element_tag_id($(@)) + 'img'
-              h = parseInt($(@).val())
-              $(trace).height(Math.abs(h))
-              $(trace).parent().height(Math.abs(h))
-              w = parseInt($(editor.element_tag_id($(@)) + 'width').val())
-            else
-          PictureSizeHelper.refresh_picture($(trace), w, h)
-      else
-    
-    # speech_balloons
-    ColorHelper.add_helper($('.speech-fore_color-wrap'), 'fore_color')
-    
-    $('.pettanr-comic-balloon' ).map ->
-      $(@).draggable {
-        stop: ( event, ui ) ->
-          balloon = $('.pettanr-balloon', $(@))
-          trace = editor.element_part_tag_id(balloon)
           left = $(@).position().left
           top = $(@).position().top
           $(trace + 'x').val(parseInt(left))
           $(trace + 'y').val(parseInt(top))
+        , cursor: "crosshair"
       }
     
-    $('.pettanr-balloon' ).map ->
-      $(@).resizable {
-        stop: ( event, ui ) ->
-          resize_div = $(@)
-          speech_balloon_div = resize_div.parent()
-          balloon = $('.pettanr-balloon', $(@))
-          trace = editor.element_tag_id(speech_balloon_div)
-          trace_balloon = editor.element_part_tag_id(balloon)
-          
-          resize_div.css('top', '0px')
-          resize_div.css('left', '0px')
-          w = ui.size.width
-          h = ui.size.height
-          if ui.originalPosition.top != ui.position.top
-            t = speech_balloon_div.position().top + ui.position.top
-            $(trace_balloon + 'y').val(Math.floor(t))
-            speech_balloon_div.css('top', t.toString() + 'px')
-            speech_balloon_div.css('height', h + 'px')
-          if ui.originalPosition.left != ui.position.left
-            l = speech_balloon_div.position().left + ui.position.left
-            $(trace_balloon + 'x').val(Math.floor(l))
-            speech_balloon_div.css('left', l.toString() + 'px')
-            speech_balloon_div.css('width', w + 'px')
-          $(trace_balloon + 'width').val(w)
-          $(trace_balloon + 'height').val(h)
-          speech_balloon_div.css('width', w.toString() + 'px')
-          speech_balloon_div.css('height', h.toString() + 'px')
-       resize: ( event, ui ) ->
-          resize_div = $(@)
-          speech_balloon_div = resize_div.parent()
-          balloon = $('.pettanr-balloon', $(@))
-          trace = editor.element_tag_id(speech_balloon_div)
-          trace_balloon = editor.element_part_tag_id(balloon)
-        handles: 'all',
-        autoHide: true
-      }
-    
-    $('.pettanr-comic-speech-inner' ).map ->
-      $(@).mouseover -> 
-        outer = $(@).parent()
-        sb = outer.parent()
-        trace = editor.element_tag_id(sb)
-        img = $('.pettanr-balloon', $(trace))
-        $('.ui-resizable-handle', img.parent()).map ->
-          $(@).css('display', 'block')
-      $(@).mouseout -> 
-        outer = $(@).parent()
-        sb = outer.parent()
-        trace = editor.element_tag_id(sb)
-        img = $('.pettanr-balloon', $(trace))
-        $('.ui-resizable-handle', img.parent()).map ->
-          $(@).css('display', 'none')
-          
-    
     # sync view 
     $('input').map  ->
-      if editor.element_is('speech_balloon', $(@))
+      if editor.element_is('sheet_panel', $(@))
         $(@).focusout ->
           switch $(@).attr('column')
             when 'x'
@@ -267,92 +117,9 @@ $ ->
               trace = editor.element_tag_id($(@))
               v = parseInt($(@).val()).toString() + 'px'
               $(trace).css('top', v)
-            when 'width'
-              trace = editor.element_tag_id($(@))
-              v = parseInt($(@).val())
-              $(trace).width(Math.abs(v))
-              img = $('.pettanr-balloon', $(trace))
-              img.parent().width(v)
-              img.width(v)
-            when 'height'
-              trace = editor.element_tag_id($(@))
-              v = parseInt($(@).val())
-              $(trace).height(Math.abs(v))
-              img = $('.pettanr-balloon', $(trace))
-              img.parent().height(v)
-              img.height(v)
             else
       else
-    $('textarea').map  ->
-      if editor.element_is('speech_balloon', $(@))
-        $(@).focusout ->
-          switch $(@).attr('column')
-            when 'content'
-              trace = editor.element_part_tag_id($(@))
-              wf_sel = $(trace + 'writing_format_id')
-              wf_id = parseInt(wf_sel.val())
-              v = WritingFormat.render(wf_id, $(@).val())
-              $(trace).html(v)
-    $('textarea').map  ->
-      if editor.element_is('speech_balloon', $(@))
-        switch $(@).attr('column')
-          when 'content'
-            $(@).bind('textchange', (event, previousText) ->
-              trace = editor.element_part_tag_id($(@))
-              wf_sel = $(trace + 'writing_format_id')
-              wf_id = parseInt(wf_sel.val())
-              v = WritingFormat.render(wf_id, $(@).val())
-              $(trace).html(v)
-            )
-    $('select').map  ->
-      if editor.element_is('speech_balloon', $(@))
-        $(@).change ->
-          switch $(@).attr('column')
-            when 'font_size'
-              trace = editor.element_part_tag_id($(@))
-              $(trace).css('font-size', $(@).val() + 'em')
-            when 'text_align'
-              trace = editor.element_part_tag_id($(@))
-              v = parseInt($(@).val())
-              $(trace).css('text-align', editor.text_align_texts[v])
-      else
-    $('input').map  ->
-      if editor.element_is('speech_balloon', $(@))
-        if $(@).attr('column') == 'fore_color'
-          $(@).hide()
-
-    
-    # ground-picture
-    # sync view 
-    $('input').map  ->
-      if editor.element_is('ground_picture', $(@))
-        $(@).focusout ->
-          switch $(@).attr('column')
-            when 'x', 'y'
-              trace = editor.element_tag_id($(@))
-              x = parseInt($(trace + 'x').val()).toString() + 'px'
-              y = parseInt($(trace + 'y').val()).toString() + 'px'
-              $(trace).css('background-position', x + ' ' + y)
-    $('select').map  ->
-      if editor.element_is('ground_picture', $(@))
-        $(@).change ->
-          switch $(@).attr('column')
-            when 'repeat'
-              trace = editor.element_tag_id($(@))
-              v = parseInt($(@).val())
-              $(trace).css('background-repeat', editor.repeat_texts[v])
-      else
-    
     
-    # ground_color
-    ColorHelper.add_helper($('.ground_color-code-wrap'), 'code')
-    
-    # sync view 
-    $('input').map  ->
-      if editor.element_is('ground_color', $(@))
-        if $(@).attr('column') == 'code'
-          $(@).hide()
-
     update_t = (ultrace) -> 
       t = 0
       $(ultrace + ' li').map ->
@@ -365,7 +132,7 @@ $ ->
     $('.tsort').map -> 
       $(@).sortable {
         update: ( event, ui ) ->
-          trace = editor.panel_tag_id($(@))
+          trace = editor.sheet_tag_id($(@))
           update_t(trace + 'tsort')
       }
     $('.t-sort li').map -> 
@@ -388,7 +155,7 @@ $ ->
     $('.zsort').map -> 
       $(@).sortable {
         update: ( event, ui ) ->
-          trace = editor.panel_tag_id($(@))
+          trace = editor.sheet_tag_id($(@))
           update_z(trace + 'zsort')
       }
     $('.z-sort li').map -> 
@@ -396,21 +163,8 @@ $ ->
     
     # all
     # disable form actions
-    # hide submit buttons
-    $('.edit_panel_picture' ).map ->
-      $(@).submit ->
-        false
-    $('.edit_speech_balloon' ).map ->
-      $(@).submit ->
-        false
-    $('.edit_ground_picture' ).map ->
-      $(@).submit ->
-        false
-    $('.edit_ground_color' ).map ->
-      $(@).submit ->
-        false
     
-    $('.edit_panel' ).map ->
+    $('.edit_sheet' ).map ->
       if $(@).attr('jqform')
       else
         $(@).submit ->
index 6ab261d..2985798 100644 (file)
@@ -41,14 +41,13 @@ class SheetsController < ApplicationController
 
   def play
     @sheet = Sheet.show(params[:id], [@user, @admin])
-    @sheet_panels = SheetPanel.play_list(@sheet, @author)
     respond_to do |format|
       format.html {
         if @author
           @new_panels = Panel.mylist(@author, 1, 5)
         end
       }
-      format.json {render text: SheetPanel.list_as_json_text(@sheet_panels, @author)}
+      format.json {render json: @sheet.to_json(Sheet.show_json_opt)}
       format.jsonp {
         render :json => "callback(" + @sheet_panels.to_json_list + ");"
       }
@@ -101,11 +100,14 @@ class SheetsController < ApplicationController
   def create
     @sheet = Sheet.new
     @sheet.supply_default 
-    @sheet.attributes = params[:sheet]
-    @sheet.overwrite @author
+    jsn = nil
+    if params[:json]
+      jsn = JSON.parse_no_except(params[:json])
+    end
+    @prm = params[:sheet] || jsn
 
     respond_to do |format|
-      if @sheet.save
+      if @sheet.store @prm, @author
         flash[:notice] = I18n.t('flash.notice.created', :model => Sheet.model_name.human)
         format.html { redirect_to @sheet }
         format.json { render json: @sheet.to_json(Sheet.show_json_opt), status: :created, location: @sheet }
@@ -119,10 +121,13 @@ class SheetsController < ApplicationController
 
   def update
     @sheet = Sheet.edit(params[:id], @author)
-    @sheet.attributes = params[:sheet]
-    @sheet.overwrite @author
+    jsn = nil
+    if params[:json]
+      jsn = JSON.parse(params[:json])
+    end
+    @prm = params[:sheet] || jsn
     respond_to do |format|
-      if @sheet.save
+      if @sheet.store @prm, @author
         flash[:notice] = I18n.t('flash.notice.updated', :model => Sheet.model_name.human)
         format.html { redirect_to @sheet }
         format.json { head :ok }
index eb9cd35..afe4b8d 100644 (file)
@@ -7,6 +7,7 @@ class Sheet < ActiveRecord::Base
   validates :width, :presence => true, :numericality => true, :natural_number => true
   validates :height, :presence => true, :numericality => true, :natural_number => true
   validates :visible, :presence => true, :numericality => true, :inclusion => {:in => 0..1}
+  accepts_nested_attributes_for :sheet_panels, :allow_destroy => true
   before_validation :valid_encode
   
   def valid_encode
@@ -16,6 +17,27 @@ class Sheet < ActiveRecord::Base
     end
   end
   
+  def self.each_element_class_names
+    {'SheetPanel' => 'sheet_panels'}.each do |k, n|
+      yield k
+    end
+  end
+  
+  def self.class_name_to_class k
+    Object.const_get k
+  end
+  
+  def self.each_element_classes
+    self.each_element_class_names do |k|
+      e = self.class_name_to_class k
+      yield e
+    end
+  end
+  
+  def elements_by_class_name class_name
+    self.__send__ class_name.tableize
+  end
+  
   def supply_default
     self.visible = 0 if self.visible.blank?
   end
@@ -46,6 +68,18 @@ class Sheet < ActiveRecord::Base
     visible? au
   end
   
+  def tag_id
+    'sheet' + self.tag_sheet_id
+  end
+  
+  def tag_sheet_id
+    self.new_record? ? '0' : self.id.to_s
+  end
+  
+  def field_tag_id f
+    self.tag_id + f.to_s
+  end
+  
   def self.default_page_size
     25
   end
@@ -143,10 +177,109 @@ class Sheet < ActiveRecord::Base
     {:include => {:sheet_panels => {:include => {:panel => {}}}, :author => {}}}
   end
   
+  def parts_element
+    r = []
+    self.class.each_element_class_names do |k|
+      r += (self.elements_by_class_name(k) || [])
+    end
+    r
+  end
+  
+  def zorderd_elements
+    res = []
+    self.parts_element.each do |e|
+      res[e.z-1] = e
+    end
+    res
+  end
+  
+  def sheet_elements
+    res = []
+    self.parts_element.each do |e|
+      res[e.t] = e
+    end
+    res
+  end
+  
+  def new_t
+    self.sheet_elements.size
+  end
+  
+  def new_z
+    self.sheet_elements.size + 1
+  end
+  
   def self.visible_count
     Sheet.count 'visible > 0'
   end
   
+  def self.collect_element_value elements, name
+    elements.map {|e|
+      e.map {|o|
+        if o['_destroy'] or o[:_destroy]
+          nil
+        else
+          o[name]
+        end
+      }.compact
+    }.flatten
+  end
+  
+  def self.validate_serial ary, offset = 0
+    i = offset
+    ary.compact.sort.each do |n|
+      break false unless n == i
+      i += 1
+    end
+    ary.compact.size == i - offset
+  end
+  
+  def self.validate_element_serial elements, name, offset = 0
+    Sheet.validate_serial(Sheet.collect_element_value(elements, name), offset)
+  end
+  
+  def self.validate_elements_serial c
+    c.map {|conf|
+      Sheet.validate_element_serial(conf[:elements], conf[:name], conf[:offset]) ? nil : false
+    }.compact.empty?
+  end
+  
+  def validate_serial_list
+    l = []
+    self.class.each_element_class_names do |k|
+      l << self.elements_by_class_name(k)
+    end
+#    l = [self.sheet_panels]
+    [
+      {:elements => l, :name => :t, :offset => 0}, 
+      {:elements => l, :name => :z, :offset => 1}
+    ]
+  end
+  
+  def validate_child
+#    r1 = Panel.validate_elements_id validate_id_list
+    Sheet.validate_elements_serial validate_serial_list
+  end
+  
+  def store attr, au
+    if attr == false
+      self.errors.add :base, I18n.t('errors.invalid_json')
+      return false
+    end
+    self.attributes = attr
+    self.overwrite au
+    res = false
+    Sheet.transaction do
+      res = self.save
+      unless validate_child
+        res = false
+        self.errors.add :base, I18n.t('errors.invalid_t')
+        raise ActiveRecord::Rollback
+      end
+    end
+    res
+  end
+  
   def destroy_with_sheet_panel
     res = false
     Sheet.transaction do
@@ -171,4 +304,12 @@ class Sheet < ActiveRecord::Base
     }.join
   end
   
+  def licensed_pictures
+    r = {}
+    self.sheet_elements.each do |elm|
+      r.merge!(elm.licensed_pictures)
+    end
+    r
+  end
+  
 end
index 6eb7c72..2612c56 100644 (file)
@@ -16,8 +16,13 @@ class SheetPanel < ActiveRecord::Base
     self.panel_id = nil
     self.x = 15
     self.y = 15
-    self.z = 1
-    self.t = nil
+    if self.sheet
+      self.t = self.sheet.new_t 
+      self.z = self.sheet.new_z 
+    else
+      self.z = 1
+      self.t = nil
+    end
   end
   
   def overwrite au
@@ -182,12 +187,12 @@ class SheetPanel < ActiveRecord::Base
     '[' + ary.map {|i| i.sheet_panel_as_json(au) }.join(',') + ']'
   end
   
-  def self.licensed_pictures sheet_panels
-    r = {}
-    sheet_panels.each do |sheet_panel|
-      r.merge!(sheet_panel.panel.licensed_pictures) if sheet_panel.panel
+  def licensed_pictures
+    if self.panel
+      self.panel.licensed_pictures
+    else
+      []
     end
-    r
   end
   
   def self.new_t sheet_id
@@ -296,4 +301,120 @@ class SheetPanel < ActiveRecord::Base
     res
   end
   
+    # element.rb
+    def self.colum_structures
+      @@colum_structures ||= {
+      }
+    end
+    
+    def self.path_name with_engine = false
+      self.to_s.tableize
+    end
+    
+    def new_index
+      @new_index
+    end
+    
+    def new_index= v
+      @new_index = v
+    end
+    
+    def new_sheet
+      @new_sheet
+    end
+    
+    def new_sheet= v
+      @new_sheet = v
+    end
+    
+    def get_sheet
+      self.sheet || @new_sheet
+    end
+    
+    def tag_id c = nil
+      'sheet' + self.tag_sheet_id + self.tag_element_type + self.tag_element_id + c.to_s
+    end
+    
+    def field_tag_id f
+      self.tag_id + f.to_s
+    end
+    
+    def tag_sheet_id
+      self.get_sheet.new_record? ? '0' : self.get_sheet.id.to_s
+    end
+    
+    def tag_element_id
+      self.new_record? ? '0' : self.id.to_s
+    end
+    
+    def tag_element_type
+      'sheet_panel'
+    end
+    
+    def tag_new_index
+      self.new_index.to_s
+    end
+    
+    def path_name with_engine = false
+      self.class.path_name(with_engine)
+    end
+    
+    def form_template with_engine = false
+      self.path_name(with_engine) + '/form'
+    end
+    
+    def scenario_template with_engine = false
+      self.path_name(with_engine) + '/scenario'
+    end
+    
+    def element_face_template with_engine = false
+      self.path_name(with_engine) + '/element_face'
+    end
+    
+    def form_helper_template(colum_name)
+      self.class.colum_structures[colum_name][:helper]
+    end
+    
+    def tag_attributes column = nil, opt = {}
+      {
+        :id => self.field_tag_id(column), :sheet_id => self.tag_sheet_id, 
+        :element_id => self.tag_element_id, :element_type => self.tag_element_type
+      }.merge(opt)
+    end
+    
+    def field_tag_attributes column, no_attr, opt = {}
+      self.tag_attributes(column).merge(
+        {:column => column, :new_index => self.tag_new_index, :no_attr => no_attr}
+      ).merge(opt)
+    end
+    
+    #render element by body
+    def any_tag_attributes name = nil, opt = {}
+      r = self.tag_attributes(name)
+      r.merge!(
+        {:new_index => self.tag_new_index}
+      ) if self.new_index
+      r.merge(opt)
+    end
+    
+    def select_tag_attributes(selected, column, no_attr)
+      [
+        :last, :first, 
+        {:html => {:selected => selected}}, 
+        self.field_tag_attributes(column, no_attr)
+      ]
+    end
+    
+    def tag_attr column = nil, opt = {}
+      self.tag_attributes(column, opt).to_attr
+    end
+    
+    def field_tag_attr column, no_attr, opt = {}
+      self.field_tag_attributes(column, no_attr, opt).to_attr
+    end
+    
+    def any_tag_attr name = nil, opt = {}
+      self.any_tag_attributes(name, opt).to_attr
+    end
+    
 end
diff --git a/app/views/sheet_panels/_element.html.erb b/app/views/sheet_panels/_element.html.erb
new file mode 100644 (file)
index 0000000..56e44e4
--- /dev/null
@@ -0,0 +1,6 @@
+<div <%= raw elm.any_tag_attr() -%> class="sheet_panel" style="top:<%= elm.y %>px; left:<%= elm.x %>px; z-index:<%= elm.z %>;">
+  <% panel = Panel.show elm.panel, author -%>
+  <% if panel -%>
+    <%= render 'panels/body', :panel => panel, :author => author, :spot => nil %>
+  <% end %>
+</div>
diff --git a/app/views/sheet_panels/_element_face.html.erb b/app/views/sheet_panels/_element_face.html.erb
new file mode 100644 (file)
index 0000000..a1d3a1e
--- /dev/null
@@ -0,0 +1,8 @@
+<div class="elements-tab-face-icon">
+  <%= panel_icon(:object => elm.panel, :size => 64) %>
+</div>
+<span class="elements-tab-face-caption">
+  <%= h(truncate(elm.panel.caption, :length => 15)) -%>
+</span>
+<div class="elements-tab-face-end">
+</div>
index 238fe21..6f178a8 100644 (file)
@@ -1,32 +1,28 @@
-<%= form_for(@sheet_panel) do |f| %>
-  <%= render 'system/error_explanation', :obj => @sheet_panel %>
+<%= form_for(elm) do |f| %>
+  <%= render 'system/error_explanation', :obj => elm %>
 
   <div class="field">
-    <%= f.label :sheet_id %><br />
-    <%= f.number_field :sheet_id %>
-  </div>
-  <div class="field">
-    <%= f.label :x %><br />
-    <%= f.number_field :x %>
-  </div>
-  <div class="field">
-    <%= f.label :y %><br />
-    <%= f.number_field :y %>
-  </div>
-  <div class="field">
-    <%= f.label :z %><br />
-    <%= f.number_field :z %>
-  </div>
-  <div class="field">
-    <%= f.label :t %><br />
-    <%= f.number_field :t %>
+    <%= f.label :x %>
+    <%= f.number_field :x, elm.field_tag_attributes(:x, no_attr, :size => 5) %>
+
+    <%= f.label :y %>
+    <%= f.number_field :y, elm.field_tag_attributes(:y, no_attr, :size => 5) %>
   </div>
   <div class="field">
-    <%= f.label :panel_id %><br />
-    <%= f.number_field :panel_id %>
+    <%= f.label :z %>
+    <%= f.number_field :z, elm.field_tag_attributes(:z, no_attr, :size => 5) %>
+
+    <%= f.label :t %>
+    <%= f.number_field :t, elm.field_tag_attributes(:t, no_attr, :size => 5) %>
   </div>
 
+  <%= f.hidden_field :panel_id, elm.field_tag_attributes(:panel_id, no_attr) %>
+  <%= f.hidden_field :sheet_id, elm.field_tag_attributes(:sheet_id, no_attr) %>
+  <% unless elm.new_record?  %>
+    <%= f.hidden_field :id, elm.field_tag_attributes(:id, no_attr) %>
+  <% end %>
+
   <div class="actions">
-    <%= f.submit %>
+    <%= f.submit t('sheet_panels.submit'), :class => "submit" %>
   </div>
 <% end %>
index 09251ee..6743faa 100644 (file)
@@ -1,21 +1,20 @@
-<% if sheet.own? author -%>
-  <%= form_for(sheet) do |f| %>
-    <div class="field">
-      <%= f.label :caption %><br />
-      <%= f.text_field :caption %>
-    </div>
-    <div class="field">
-      <%= f.label :visible %><br />
-      <%= f.collection_select :visible, t_select_items(MagicNumber['sheet_visible_items']), :last, :first, :html => {:selected => @sheet.visible} %>
-    </div>
-    <div class="actions">
-      <%= f.submit %>
-    </div>
-  <% end %>
-<% else %>
-<% end %>
-
-<div>
-  <%= link_to author_icon(:object => sheet.author, :size => 25), author_path(sheet.author) %>
-  <%= link_to h(truncate(sheet.author.name, :length => 12)), author_path(sheet.author) %>
-</div>
+<h1>
+  <%= link_to sheet_icon(:object => sheet, :size => 25), sheet_path(sheet) %>
+  <%= link_to h(sheet.caption), play_sheet_path(sheet) %>
+</h1>
+<table class="no-border" style="margin: 0px; padding: 0px; width=100%">
+  <tr>
+    <td>
+    </td>
+    <td>
+      <%= link_to author_icon(:object => sheet.author, :size => 17), author_path(sheet.author) %>
+      <%= link_to h(truncate(sheet.author.name, :length => 12)), play_sheet_path(sheet.author) %>
+    </td>
+    <td>
+      <% if sheet.own? author %>
+        <%= link_to t('link.edit'), edit_sheet_path(sheet) %>
+        <%= link_to t('link.destroy'), sheet_path(sheet), :method => :delete %>
+      <% end %>
+    </td>
+  </tr>
+</table>
diff --git a/app/views/sheet_panels/_scenario.html.erb b/app/views/sheet_panels/_scenario.html.erb
new file mode 100644 (file)
index 0000000..e63b753
--- /dev/null
@@ -0,0 +1,3 @@
+<div id="<%= elm.tag_id('scenario') -%>" class="sheet_panel-scenario">
+  <%=  %>
+</div>
index 1d67f75..1264b23 100644 (file)
@@ -1,4 +1,4 @@
 <h1><%= t('.title') %></h1>
 <p id="notice"><%= notice %></p>
 
-<%= render 'form' %>
+<%= render @sheet_panel.form_template, :elm => @sheet_panel, :no_attr => 0 %>
index f33a2f8..0a817c8 100644 (file)
@@ -1,3 +1,3 @@
 <h1><%= t('.title') %></h1>
 
-<%= render 'form' %>
+<%= render @sheet_panel.form_template, :elm => @sheet_panel, :no_attr => 0 %>
index d7f2ba9..cdc19f2 100644 (file)
@@ -1,11 +1,7 @@
-<div id="sheet-<%= sheet.id -%>" class="sheet" style="width:<%= sheet.width %>px;height:<%= sheet.height %>px;">
+<div id="<%= sheet.tag_id -%>" sheet_id="<%= sheet.tag_sheet_id -%>" class="sheet" style="width:<%= sheet.width %>px;height:<%= sheet.height %>px;">
   <% if sheet.visible? author -%>
-    <% sheet_panels.each do |sheet_panel| %>
-      <div id="sheet_panel-<%= sheet_panel.id -%>" class="sheet_panel" style="top:<%= sheet_panel.y %>px; left:<%= sheet_panel.x %>px; z-index:<%= sheet_panel.z %>;">
-        <% if sheet_panel.panel -%>
-          <%= render 'panels/body', :panel => sheet_panel.panel, :author => author, :spot => nil %>
-        <% end %>
-      </div>
+    <% sheet.sheet_elements.each do |elm| %>
+      <%= render elm.class.to_s.tableize + '/element', :elm => elm, :author => author %>
     <% end %>
   <% else %>
     <h2><%= t('sheets.hidden') %></h2>
diff --git a/app/views/sheets/_element_tab.html.erb b/app/views/sheets/_element_tab.html.erb
new file mode 100644 (file)
index 0000000..e6a8f72
--- /dev/null
@@ -0,0 +1,8 @@
+<li id="<%= elm.field_tag_id(:element_tab) -%>" sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+  <a href="#elements-tabs-<%= elm.t -%>">
+    <div class="elements-tab">
+      <%= render elm.element_face_template, :elm => elm %>
+    </div>
+  </a>
+  <button class="ui-icon-destroy" id="<%= elm.field_tag_id(:_destroy_button) -%>" sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>"></button>
+</li>
index 83c147f..c061d5e 100644 (file)
@@ -1,27 +1,99 @@
-<%= form_for(@sheet) do |f| %>
-  <%= render 'system/error_explanation', :obj => @sheet %>
+<div id="tabs" class="sheet-editor" sheet_id="<%= @sheet.tag_sheet_id -%>" current="1">
+  <ul>
+    <li><a href="#tabs-1">sheet</a></li>
+    <li><a href="#tabs-2">elements</a></li>
+    <li><a href="#tabs-3">t order</a></li>
+    <li><a href="#tabs-4">z order</a></li>
+    <li><a href="#tabs-5">new</a></li>
+  </ul>
+  <div id="tabs-1">
+    <%= form_for(@sheet) do |f| %>
+      <%= render 'system/error_explanation', :obj => @sheet %>
+
+      <div class="field">
+        <%= f.label :caption %>
+        <%= f.text_field :caption, :id => @sheet.field_tag_id(:caption), :sheet_id => @sheet.tag_sheet_id, :column => :caption -%>
+      </div>
+      <div class="field">
+        <%= f.label :width %>
+        <%= f.number_field :width, :size => 5, :id => @sheet.field_tag_id(:width), :sheet_id => @sheet.tag_sheet_id, :column => :width %>
+
+        <%= f.label :height %>
+        <%= f.number_field :height, :size => 5, :id => @sheet.field_tag_id(:height), :sheet_id => @sheet.tag_sheet_id, :column => :height %>
 
-  <div class="field">
-    <%= f.label :caption %><br />
-    <%= f.text_field :caption %>
+      </div>
+      <div class="field">
+        <%= f.label :visible %>
+        <%= f.collection_select :visible, t_select_items(MagicNumber['sheet_visible_items']), :last, :first, {:html => {:selected => @sheet.visible}}, {:id => @sheet.field_tag_id(:visible), :sheet_id => @sheet.tag_sheet_id, :column => :visible} %>
+      </div>
+      <% unless @sheet.new_record?  %>
+        <%= f.hidden_field :id, :id => @sheet.field_tag_id(:id), :sheet_id => @sheet.tag_sheet_id, :column => :id %>
+      <% end %>
+      <div class="actions">
+        <%= f.submit 'sheets.submit', :class => "submit" %>
+      </div>
+    <% end %>
   </div>
-  <div class="field">
-    <%= f.label :width %><br />
-    <%= f.number_field :width %>
+  <div id="tabs-2">
+    <div id="elements-tabs">
+      <ul>
+        <% @sheet.sheet_elements.each do |elm| %>
+          <%= render 'element_tab', :elm => elm %>
+        <% end %>
+      </ul>
+      <% @sheet.sheet_elements.each do |elm| %>
+        <div id="<%= elm.field_tag_id(:tab_sheet) -%>" sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+          <div id="elements-tabs-<%= elm.t -%>">
+            <%= render elm.form_template, :elm => elm, :no_attr => 0 %>
+            <%= hidden_field_tag '_destroy', '', :id => elm.field_tag_id(:_destroy), :sheet_id => elm.tag_sheet_id, :element_id => elm.tag_element_id, :element_type => elm.tag_element_type, :column => :_destroy %>
+          </div>
+        </div>
+      <% end %>
+    </div>
   </div>
-  <div class="field">
-    <%= f.label :height %><br />
-    <%= f.number_field :height %>
+  <div id="tabs-3">
+    <div class="tsort-box">
+      <ul id="<%= @sheet.tag_id -%>tsort" class="tsort tsort-tabs-nav" sheet_id="<%= @sheet.tag_sheet_id -%>">
+        <% @sheet.sheet_elements.each do |elm| %>
+          <li id="<%= elm.field_tag_id(:tsort) -%>" sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+            <div class="elements-tab">
+              <%= render elm.path_name + '/element_face', :elm => elm %>
+            </div>
+          </li>
+        <% end %>
+      </ul>
+    </div>
+    <div id="<%= @sheet.tag_id -%>scenario" class="scenario" sheet_id="<%= @sheet.tag_sheet_id -%>">
+      <% @sheet.sheet_elements.each do |elm| %>
+        <div sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+          <%= render elm.scenario_template, :elm => elm, :no_attr => 0 %>
+        </div>
+      <% end %>
+    </div>
+    <div class="tsort-row-break">
+    </div>
   </div>
-  <div class="field">
-    <%= f.label :visible %><br />
-    <%= f.collection_select :visible, t_select_items(MagicNumber['sheet_visible_items']), :last, :first, :html => {:selected => @sheet.visible} %>
+  <div id="tabs-4">
+    <div class="zsort-box">
+      <ul id="<%= @sheet.tag_id -%>zsort" class="zsort zsort-tabs-nav" sheet_id="<%= @sheet.tag_sheet_id -%>">
+        <% @sheet.zorderd_elements.each do |elm| %>
+          <li id="<%= elm.field_tag_id(:zsort) -%>" sheet_id="<%= elm.tag_sheet_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+            <div class="elements-tab">
+              <%= render elm.class.to_s.tableize + '/element_face', :elm => elm %>
+            </div>
+          </li>
+        <% end %>
+      </ul>
+    </div>
   </div>
-  <div class="field">
-    <%= f.label :author_id %><br />
-    <%= h @author.name %>
+  <div id="tabs-5">
   </div>
-  <div class="actions">
-    <%= f.submit %>
+</div>
+<%= form_for(@sheet, :html => {:jqform => 'pettanr-sheet-form'}) do |f| %>
+  <%= render 'system/error_explanation', :obj => @sheet %>
+
+  <%= text_field_tag "json", '', :id => 'pettanr-sheet-json' %>
+  <div>
+    <%= submit_tag t('sheets.create_from_json'), :id => 'pettanr-sheet-submit' -%>
   </div>
 <% end %>
index 663de28..ad2f5f4 100644 (file)
@@ -1,9 +1,9 @@
-<%= render 'sheets/body', :sheet_panels => sheet_panels, :sheet => sheet, :author => author %>
+<%= render 'sheets/body', :sheet => sheet, :author => author %>
 <div class="sheet-data">
-  <% sheet_panels.each do |sheet_panel| %>
+  <% sheet.sheet_elements.each do |sheet_panel| %>
     <%= render 'sheet_panels/play_footer', :sheet_panel => sheet_panel, :author => author %>
   <% end %>
-  <%= render 'sheet_panels/licensed_pictures', :licensed_pictures => SheetPanel.licensed_pictures(sheet_panels) %>
+  <%= render 'sheet_panels/licensed_pictures', :licensed_pictures => @sheet.licensed_pictures %>
 </div>
 <div class="sheet-break">
 </div>
index 1d67f75..203d91a 100644 (file)
@@ -1,4 +1,16 @@
 <h1><%= t('.title') %></h1>
 <p id="notice"><%= notice %></p>
 
-<%= render 'form' %>
+<div id="<%= @sheet.tag_id -%>wrapper" sheet_id="<%= @sheet.tag_sheet_id -%>" class="pettanr-sheet-wrapper" editable="true">
+  <%= render 'sheets/body', :sheet => @sheet, :author => @author %>
+  <div class="sheet-data">
+    <% @sheet.sheet_elements.each do |sheet_panel| %>
+      <%= render 'sheet_panels/play_footer', :sheet_panel => sheet_panel, :author => @author %>
+    <% end %>
+  </div>
+  <div class="sheet-break">
+  </div>
+</div>
+<%= render 'form', :sheet => @sheet %>
+<%= link_to t('link.destroy'), sheet_path(@sheet), :method => :delete %>
+<%= render 'sheet_panels/licensed_pictures', :licensed_pictures => @sheet.licensed_pictures %>
index 39ae7be..3371291 100644 (file)
@@ -1,5 +1,13 @@
 <h1><%= t('.title') %></h1>
 
-<%= render 'form' %>
-
-<%= link_to t('link.back'), sheets_path %>
+<div id="<%= @sheet.tag_id -%>wrapper" sheet_id="<%= @sheet.tag_sheet_id -%>" class="pettanr-sheet-wrapper" editable="true">
+  <%= render 'sheets/body', :sheet => @sheet, :author => @author %>
+  <div class="sheet-data">
+    <% @sheet.sheet_elements.each do |sheet_panel| %>
+      <%= render 'sheet_panels/play_footer', :sheet_panel => sheet_panel, :author => @author %>
+    <% end %>
+  </div>
+  <div class="sheet-break">
+  </div>
+</div>
+<%= render 'form', :sheet => @sheet %>
index 094ce8e..1dfe173 100644 (file)
@@ -2,10 +2,12 @@
 <p id="notice"><%= notice %></p>
 <%= render 'sheet_panels/play_header', :sheet => @sheet, :author => @author %>
 
-<% if @sheet_panels.empty? -%>
+<% if @sheet.sheet_elements.empty? -%>
   <h2><%= t('sheet_panels.sheet.empty') %></h2>
 <% else %>
-  <%= render 'sheets/standard', :sheet_panels => @sheet_panels, :sheet => @sheet, :author => @author %>
+  <div id="<%= @sheet.tag_id -%>wrapper" sheet_id="<%= @sheet.tag_sheet_id -%>" class="pettanr-sheet-wrapper" editable="true">
+    <%= render 'sheets/standard', :sheet => @sheet, :author => @author %>
+  </div>
 <% end %>
 <% if @sheet.own? @author -%>
   <h3><%= t('sheet_panels.append.new_panels') -%></h3>
index 92c7477..f39894d 100644 (file)
@@ -2,43 +2,12 @@
 <h1><%= t('.title') %></h1>
 <p id="notice"><%= notice %></p>
 
-<p>
-  <b><%= t_m 'Sheet.caption' -%>:</b>
-  <%= link_to h(@sheet.caption), play_sheet_path(@sheet) %>
-</p>
+<%= render 'standard', :sheet => @sheet, :author => @author %>
 
-<p>
-  <b><%= t_m 'Sheet.width' -%>:</b>
-  <%= h(@sheet.width) %>
-</p>
+<% if @sheet.own? @author %>
+  <%= link_to t('link.edit'), edit_sheet_path(@sheet) %>
+  <%= link_to t('link.destroy'), sheet_path(@sheet), :method => :delete %>
 
-<p>
-  <b><%= t_m 'Sheet.height' -%>:</b>
-  <%= h(@sheet.height) %>
-</p>
-
-<p>
-  <b><%= t_m 'Sheet.visible' -%>:</b>
-  <%= t_selected_item('sheet_visible_items', @sheet.visible) %>
-</p>
-
-<p>
-  <b><%= t_m 'Sheet.author_id' -%>:</b>
-  <%= link_to h(@sheet.author.name), author_path(@sheet.author) %>
-</p>
-
-<p>
-  <b><%= t_m 'Sheet.created_at' -%>:</b>
-  <%= l @sheet.created_at %>
-</p>
-
-<p>
-  <b><%= t_m 'Sheet.updated_at' -%>:</b>
-  <%= l @sheet.updated_at %>
-</p>
-
-<%= link_to t('link.edit'), edit_sheet_path(@sheet) %>
-<% if @sheet.own? @author -%>
   <h3><%= t('sheet_panels.append.new_panels') -%></h3>
   <table>
     <% @new_panels.each do |panel| %>
index 4217dfc..27affa0 100644 (file)
@@ -670,6 +670,7 @@ ja:
     browse:
       title: 用紙 生単票
     hidden: 権限がありません
+    create_from_json: jsonデータからコマ作成する
   sheet_panels:
     index:
       title: 紙コマ一覧
@@ -689,6 +690,7 @@ ja:
       title: 紙コマ 生一覧
     browse:
       title: 紙コマ 生単票
+    submit: 作成する
     move: 移動
     append:
       panel: このコマを追加する
index 0109ad1..289f3ed 100644 (file)
@@ -267,7 +267,7 @@ if MagicNumber['run_mode'] == 1
   
   describe '閲覧に於いて' do
     before do
-      @sheet = FactoryGirl.create :sheet, :author_id => @user.author.id
+      @sheet = FactoryGirl.create :sheet, :author_id => @user.author.id, :caption => 'normal'
       @panel = FactoryGirl.create :panel, :author_id => @author.id
       @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id
       Sheet.stub(:show).with(@sheet.id.to_s, [@user, nil]).and_return(@sheet)
@@ -281,16 +281,8 @@ if MagicNumber['run_mode'] == 1
         Sheet.should_receive(:show).with(@sheet.id.to_s, [@user, nil]).exactly(1)
         get :play, :id => @sheet.id
       end
-      it '紙コマモデルにプレイリスト取得を問い合わせている' do
-        SheetPanel.should_receive(:play_list).with(@sheet, @author).exactly(1)
-        get :play, :id => @sheet.id
-      end
     end
     context 'つつがなく終わるとき' do
-      it '@sheet_panelsにリストを取得している' do
-        get :play, :id => @sheet.id
-        assigns(:sheet_panels).should have_at_least(3).items
-      end
       context 'html形式' do
         it 'ステータスコード200 OKを返す' do
           get :play, :id => @sheet.id
@@ -310,21 +302,15 @@ if MagicNumber['run_mode'] == 1
           get :play, :id => @sheet.id, :format => :json
           lambda{JSON.parse(response.body)}.should_not raise_error(JSON::ParserError)
         end
-        it '紙コマモデルに紙コマリストのjson出力を問い合わせている' do
-          SheetPanel.should_receive(:list_as_json_text).exactly(1)
-          get :play, :id => @sheet.id, :format => :json
-        end
-        it 'データがリスト構造になっている' do
-          get :play, :id => @sheet.id, :format => :json
-          json = JSON.parse response.body
-          json.should have_at_least(3).items
+        it '用紙モデルにjson単体出力オプションを問い合わせている' do
+          Sheet.should_receive(:show_json_opt).exactly(1)
+          get :show, :id => @sheet.id, :format => :json
         end
-        it 'ã\83ªã\82¹ã\83\88ã\81®å\85\88é ­ã\81\8fã\82\89ã\81\84ã\81¯ç´\99ã\82³ã\83\9eã\81£ã\81½ã\81\84ã\82\82ã\81®ã\81§ã\81\82ã\81£ã\81¦æ¬²ã\81\97ã\81\84' do
+        it 'ã\83\87ã\83¼ã\82¿ã\81\8cã\82¢ã\83¬ã\81«ã\81ªã\81£ã\81¦ã\81\84ã\82\8b' do
           get :play, :id => @sheet.id, :format => :json
           json = JSON.parse response.body
-          json.first.has_key?("panel_id").should be_true
-          json.first.has_key?("sheet_id").should be_true
-          json.first.has_key?("author_id").should be_true
+          json["caption"].should match(/normal/)
+          json["visible"].should_not be_nil
         end
       end
     end
@@ -512,20 +498,27 @@ if MagicNumber['run_mode'] == 1
       @attr = FactoryGirl.attributes_for(:sheet, :author_id => @author.id, :caption => 'normal')
     end
     context '事前チェックしておく' do
-      it '用紙モデルにデフォルト値補充を依頼している' do
-        Sheet.any_instance.should_receive(:supply_default).exactly(1)
+      it 'sheetがパラメータにあれば、展開する' do
         post :create, :sheet => @attr
+        assigns(:prm)['caption'].should eq 'normal'
       end
-      it '用紙モデルにカラム値復元を依頼している' do
-        Sheet.any_instance.should_receive(:attributes=).exactly(1)
-        post :create, :sheet => @attr
+      it 'jsonがパラメータにあれば、展開する' do
+        post :create, :json => FactoryGirl.attributes_for(:sheet, :caption => 'json prm').to_json
+        assigns(:prm)['caption'].should eq 'json prm'
       end
-      it '用紙モデルに上書き補充を依頼している' do
-        Sheet.any_instance.should_receive(:overwrite).exactly(1)
+      it 'sheet・json両パラメータがあれば、sheetを優先して展開する' do
+        post :create, {
+          :sheet => FactoryGirl.attributes_for(:sheet, :caption => 'normal'), 
+          :json => FactoryGirl.attributes_for(:sheet, :caption => 'json prm').to_json
+        }
+        assigns(:prm)['caption'].should eq 'normal'
+      end
+      it '用紙モデルにデフォルト値補充を依頼している' do
+        Sheet.any_instance.should_receive(:supply_default).exactly(1)
         post :create, :sheet => @attr
       end
       it 'モデルに保存依頼する' do
-        Sheet.any_instance.should_receive(:save).exactly(1)
+        Sheet.any_instance.should_receive(:store).exactly(1)
         post :create, :sheet => @attr
       end
     end
@@ -537,19 +530,19 @@ if MagicNumber['run_mode'] == 1
       end
       context 'html形式' do
         it 'ステータスコード302 Foundを返す' do
-          Sheet.any_instance.stub(:save).and_return(true)
+          Sheet.any_instance.stub(:store).and_return(true)
           post :create, :sheet => @attr
           response.status.should eq 302
         end
         it '作成された用紙の表示ページへ遷移する' do
-#          Sheet.any_instance.stub(:save).and_return(true)
+#          Sheet.any_instance.stub(:store).and_return(true)
           post :create, :sheet => @attr
           response.should redirect_to(Sheet.last)
         end
       end
       context 'json形式' do
         it 'ステータスコード200 OKを返す' do
-#          Sheet.any_instance.stub(:save).and_return(true)
+#          Sheet.any_instance.stub(:store).and_return(true)
           post :create, :sheet => @attr, :format => :json
           response.should be_success 
         end
@@ -749,37 +742,45 @@ if MagicNumber['run_mode'] == 1
       sign_in @user
     end
     context '事前チェックしておく' do
-      it '用紙モデルに編集取得を問い合わせている' do
-        Sheet.stub(:edit).with(any_args()).and_return @sheet
-        Sheet.should_receive(:edit).exactly(1)
+      it 'sheetがパラメータにあれば、展開する' do
         put :update, :id => @sheet.id, :sheet => @attr
+        assigns(:prm)['caption'].should eq 'updated caption'
       end
-      it '用紙モデルにカラム値復元を依頼している' do
-        Sheet.any_instance.should_receive(:attributes=).exactly(1)
-        put :update, :id => @sheet.id, :sheet => @attr
+      it 'jsonがパラメータにあれば、展開する' do
+        put :update, :id => @sheet.id, :json => FactoryGirl.attributes_for(:sheet, :caption => 'json caption').to_json
+        assigns(:prm)['caption'].should eq 'json caption'
+      end
+      it 'sheet・json両パラメータがあれば、sheetを優先して展開する' do
+        put :update, {
+          :id => @sheet.id, 
+          :sheet => FactoryGirl.attributes_for(:sheet, :caption => 'updated caption'), 
+          :json => FactoryGirl.attributes_for(:sheet, :caption => 'json caption').to_json
+        }
+        assigns(:prm)['caption'].should eq 'updated caption'
       end
-      it '用紙モデルに上書き補充を依頼している' do
-        Sheet.any_instance.should_receive(:overwrite).exactly(1)
+    end
+    context 'つつがなく終わるとき' do
+      it '用紙モデルに編集取得を問い合わせている' do
+        Sheet.stub(:edit).with(any_args()).and_return @sheet
+        Sheet.should_receive(:edit).exactly(1)
         put :update, :id => @sheet.id, :sheet => @attr
       end
       it 'モデルに更新を依頼する' do
-        Sheet.any_instance.stub(:save).with(any_args).and_return true
-        Sheet.any_instance.should_receive(:save).exactly(1)
+        Sheet.any_instance.stub(:store).with(any_args).and_return true
+        Sheet.any_instance.should_receive(:store).exactly(1)
         put :update, :id => @sheet.id, :sheet => @attr
       end
       it '@sheetにアレを取得している' do
         put :update, :id => @sheet.id, :sheet => @attr
         assigns(:sheet).id.should eq(@sheet.id)
       end
-    end
-    context 'つつがなく終わるとき' do
       it '更新される' do
         put :update, :id => @sheet.id, :sheet => @attr
         Sheet.find(@sheet.id).visible.should eq 0
       end
       context 'html形式' do
         it 'ステータスコード302 Foundを返す' do
-          Sheet.any_instance.stub(:save).with(any_args()).and_return(true)
+          Sheet.any_instance.stub(:store).with(any_args()).and_return(true)
           put :update, :id => @sheet.id, :sheet => @attr
           response.status.should eq 302
         end
@@ -790,12 +791,12 @@ if MagicNumber['run_mode'] == 1
       end
       context 'json形式' do
         it 'ステータスコード200 OKを返す' do
-          Sheet.any_instance.stub(:save).with(any_args()).and_return(true)
+          Sheet.any_instance.stub(:store).with(any_args()).and_return(true)
           put :update, :id => @sheet.id, :sheet => @attr, :format => :json
           response.should be_success 
         end
         it 'ページ本体は特に返さない' do
-          Sheet.any_instance.stub(:save).with(any_args()).and_return(true)
+          Sheet.any_instance.stub(:store).with(any_args()).and_return(true)
           put :update, :id => @sheet.id, :sheet => @attr, :format => :json
           response.body.should match /./
         end
index 5eadaa5..14ab7b8 100644 (file)
@@ -878,48 +878,6 @@ describe SheetPanel do
     end
   end
   
-  describe 'ライセンス素材に於いて' do
-    before do
-      #コマを作成しておく。
-      @op2 = FactoryGirl.create :original_picture, :artist_id => @artist.id
-      @p2 = FactoryGirl.create :picture, :original_picture_id => @op2.id, :license_id => @license.id, :artist_id => @artist.id
-      @rp2 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op2.id, :picture_id => @p2.id
-      @panel = FactoryGirl.create :panel, :author_id => @author.id
-      @pp = FactoryGirl.create :panel_picture, :panel_id => @panel.id, :t => 0, :width => @p.width, :height => @p.height, :picture_id => @p.id
-      @panel.reload
-      @panel2 = FactoryGirl.create :panel, :author_id => @author.id
-      @pp2= FactoryGirl.create :panel_picture, :panel_id => @panel2.id, :t => 0, :width => @p2.width, :height => @p2.height, :picture_id => @p2.id
-      @panel2.reload
-      
-      @sheet = FactoryGirl.create :sheet, :author_id => @author.id
-      @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id
-      @sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel2.id
-    end
-    context '事前チェック' do
-    end
-    context 'つつがなく終わるとき' do
-    end
-    it '連想配列(値は実素材、キーは実素材id)を返している' do
-      r = SheetPanel.licensed_pictures [@sheet_panel, @sheet_panel2]
-      r.is_a?(Hash).should be_true
-      r.should have(2).items
-      r[@pp.picture_id].should eq @p
-      r[@pp2.picture_id].should eq @p2
-    end
-    context 'コマが削除されているときき' do
-      before do
-        @panel2.destroy
-      end
-      it '削除されているコマは無視する' do
-        r = SheetPanel.licensed_pictures [@sheet_panel, @sheet_panel2]
-        r.is_a?(Hash).should be_true
-        r.should have(1).items
-        r[@pp.picture_id].should eq @p
-        r[@pp2.picture_id].should be_nil
-      end
-    end
-  end
-  
   describe 't補充値に於いて' do
     before do
       @sheet = FactoryGirl.create :sheet, :author_id => @author.id
index 4cec7ed..202f5cc 100644 (file)
@@ -664,6 +664,193 @@ describe Sheet do
     end
   end
   
+  describe '検証値収集に於いて' do
+    context 'つつがなく終わるとき' do
+      it '第一パラメータで指定された配列中から第二引数のカラム値を収集している' do
+        elements = [[{:sheet_id => 1, :a => 'a'}, {:sheet_id => 2, :a => 'a'}], 
+          [{:sheet_id => 3, :a => 'a'}, {:sheet_id => 4, :a => 'a'}]]
+        r = Sheet.collect_element_value elements, :sheet_id
+        r.should eq [1, 2, 3, 4]
+      end
+      it '第一パラメータで指定された配列中から第二引数のカラム値を収集している' do
+        elements = [[{:t => 1, :a => 'a'}, {:t => 2, :a => 'a'}], 
+          [{:t => 3, :a => 'a'}, {:t => 0, :a => 'a'}]]
+        r = Sheet.collect_element_value elements, :t
+        r.should eq [1, 2, 3, 0]
+      end
+    end
+  end
+  describe 'シリアライズチェックに於いて' do
+    context 'つつがなく終わるとき' do
+      it '0からシリアライズされているならTrueを返す' do
+        r = Sheet.validate_serial [0, 1, 2]
+        r.should be_true
+      end
+      it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do
+        r = Sheet.validate_serial [0, 2, 1]
+        r.should be_true
+      end
+      it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do
+        r = Sheet.validate_serial [ 2, 1, 4, 3, 0]
+        r.should be_true
+      end
+    end
+    context 'オフセットが1のとき' do
+      it '0からシリアライズされているならFalseを返す' do
+        r = Sheet.validate_serial [0, 1, 2], 1
+        r.should be_false
+      end
+      it '1からシリアライズされているならTrueを返す' do
+        r = Sheet.validate_serial [1, 2, 3], 1
+        r.should be_true
+      end
+    end
+    context '異常なとき' do
+      it '0から始まらないならFalseを返す' do
+        r = Sheet.validate_serial [1, 2, 3]
+        r.should be_false
+      end
+      it '連続していないならFalseを返す' do
+        r = Sheet.validate_serial [0, 1, 2, 4]
+        r.should be_false
+      end
+      it '連続していないならFalseを返す' do
+        r = Sheet.validate_serial [0, 1, 2, 4, 5]
+        r.should be_false
+      end
+    end
+  end
+  describe 'シリアライズチェック単体に於いて' do
+    before do
+    end
+    context 'つつがなく終わるとき' do
+      it '検証値収集を依頼している' do
+        Sheet.should_receive(:collect_element_value).with(any_args).exactly(1)
+        Sheet.stub(:collect_element_value).with(any_args).and_return([])
+        Sheet.stub(:validate_serial).with(any_args).and_return(true)
+        r = Sheet.validate_element_serial [], :t
+      end
+      it 'シリアライズチェック依頼している' do
+        Sheet.stub(:collect_element_value).with(any_args).and_return([])
+        Sheet.should_receive(:validate_serial).with(any_args).exactly(1)
+        Sheet.stub(:validate_serial).with(any_args).and_return(true)
+        r = Sheet.validate_element_serial [], :t
+      end
+    end
+  end
+  describe '従属データの検証に於いて' do
+    context 'つつがなく終わるとき' do
+      it 'trueを返している' do
+        @sheet = FactoryGirl.create :sheet, :author_id => @author.id
+        @panel = FactoryGirl.create :panel, :author_id => @author.id
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 0, :z => 0+1)
+        )
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :z => 1+1)
+        )
+        r = @sheet.validate_child
+        r.should be_true
+      end
+    end
+    context 'tシリアライズされていないとき' do
+      it 'falseを返している' do
+        @sheet = FactoryGirl.create :sheet, :author_id => @author.id
+        @panel = FactoryGirl.create :panel, :author_id => @author.id
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 2, :z => 0+1)
+        )
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :z => 1+1)
+        )
+        r = @sheet.validate_child
+        r.should be_false
+      end
+    end
+    context 'zシリアライズされていないとき' do
+      it 'falseを返している' do
+        @sheet = FactoryGirl.create :sheet, :author_id => @author.id
+        @panel = FactoryGirl.create :panel, :author_id => @author.id
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 0, :z => 0+2)
+        )
+        @sheet.sheet_panels.create(
+          FactoryGirl.attributes_for(:sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :z => 1+1)
+        )
+        r = @sheet.validate_child
+        r.should be_false
+      end
+    end
+  end
+  describe '保存に於いて' do
+    before do
+      @attr = FactoryGirl.attributes_for :sheet
+      @sheet = Sheet.new
+      @sheet.supply_default
+    end
+    context 'つつがなく終わるとき' do
+      before do
+        Sheet.any_instance.stub(:validate_child).with(any_args).and_return(true)
+        Sheet.any_instance.stub(:save).with(any_args).and_return(true)
+      end
+      it 'コマモデルに上書き補充を依頼している' do
+        Sheet.any_instance.should_receive(:overwrite).exactly(1)
+        r = @sheet.store @attr, @author
+      end
+      it '保存を依頼している' do
+        Sheet.any_instance.should_receive(:save).with(any_args).exactly(1)
+        @sheet = FactoryGirl.build :sheet, :author_id => @author.id
+        r = @sheet.store @attr, @author
+      end
+      it '従属データの検証を依頼している' do
+        Sheet.any_instance.should_receive(:validate_child).with(any_args).exactly(1)
+        r = @sheet.store @attr, @author
+      end
+    end
+    context 'つつがなく終わるとき' do
+      before do
+        Sheet.any_instance.stub(:validate_child).with(any_args).and_return(true)
+      end
+      it 'Trueを返す' do
+        r = @sheet.store @attr, @author
+        r.should be_true
+      end
+      it '行が追加されている' do
+        Sheet.any_instance.stub(:validate_child).with(any_args).and_return(true)
+        lambda {
+          r = @sheet.store @attr, @author
+        }.should change(Sheet, :count)
+      end
+    end
+    context '不正なjsonデータのとき' do
+      before do
+      end
+      it 'エラーメッセージがセットされている' do
+        r = @sheet.store false, @author
+        @sheet.errors[:base].should_not be_blank
+      end
+    end
+    context '従属データの検証に失敗したとき' do
+      before do
+        Sheet.any_instance.stub(:save).with(any_args).and_return(true)
+        Sheet.any_instance.stub(:validate_child).with(any_args).and_return(false)
+      end
+      it 'エラーメッセージがセットされている' do
+        r = @sheet.store @attr, @author
+        @sheet.errors[:base].should_not be_blank
+      end
+    end
+    context 'カラム値がFalseしたとき' do
+      before do
+        Sheet.any_instance.stub(:validate_child).with(any_args).and_return(true)
+      end
+      it 'エラーメッセージがセットされている' do
+        r = @sheet.store false, @author
+        @sheet.errors.should_not be_empty
+      end
+    end
+  end
+  
   describe '削除に於いて' do
     before do
       @sheet = FactoryGirl.create :sheet, :author_id => @author.id