وحدة:Block diagram

This function takes a long string of text and tags in angle brackets to output a set of HTML <div> elements. This allows you to block out a diagram with arbitrarily placed rectangular elements. The main point of the module is that it allows some attributes to be applied in a "sticky" manner, so that once you set the color or position of a div, the divs coming after it will have the same values unless you change them. Though the text may still be pretty lengthy, it is much shorter than a full specification of all the divs.

Parameters

  • width and height are the width and height of the total block diagram output.
  • nowiki returns the output as nowiki source text for debugging or copying.
  • debug may return some debuglog data (very little use except when making changes to the module)
  • The first unlabelled parameter contains a large amount of text and tags to be interpreted as described below.
  • Warning: if your text contains or may in the future contain an = character, you must begin this text with 1=

Tags

  • The module takes several html attribute names and sets them to the value given. The colon and semicolon you'd use in the style must not be given.
  • The tags currently supported are left, right, top, bottom, border-style, border-width, border-color, color, background-color, text-align, vertical-align, and vcentertext
  • Some values are altered by the module:
    • A "%" is automatically added to the position attributes. Px values are not supported. This is intentional --- the intent is that the initial width and height parameters can be changed without having to rewrite the contents.
    • The right and bottom values are given as percents from the left or top, not from the right or bottom as in the HTML. This means that boxes from top 60 to bottom 80 and top 80 to bottom 100 will adjoin each other.
  • Vertical centering is special, and relies on Template:vertical center to position the text within the boxes with two additional divs inside the boxes. That template accepts a third parameter that applies to the outer div of that template, which can be fine-tunes with vcentertext. To be clear, this is a dirty way of solving the last few pixels of misalignment encountered with small text in small boxes.
  • Don't forget that you can include <span> and <div> elements, or even images, in your text. This allows you to cover any eventualities not yet implemented as tags here. Only the special tags listed above are interpreted by the module; normal Wiki tags will be ignored by it, so they should be interpreted properly. [frame:preprocess() is used on the module output]
  • Currently no effort is made to try to figure out how to size the text to fit in the boxes - you have to make sure the diagram is big enough or the text small enough on your own.
  • You may find it convenient to wrap up the output from this module in Template:Pseudo image, which can make it look like a thumbnail preview, complete with link to a file or page with more detail about its contents.

Example

is produced by:

{{#invoke:Block diagram|main|width=600|height=245|1=<border-color grey><border-width 0px 0px 0px 1px><left 30><right 30> <left 70><right 70> <border-width 0px><top 0><bottom 12><left 0><right 100><background-color #ffbcd8>Practice of Induced Abortion Methods<background-color #bdc9df><top 19><bottom 29><left 7.5><right 20>[[Manual vacuum aspiration|MVA]]<left 40><right 65>[[Dilation and evacuation|Dilation and Evacuation]]<top 38><bottom 47><left 15><right 30>[[Electric vacuum aspiration|EVA]]<left 50><right 75>[[Hysterotomy]]<left 15><right 37.5><top 56><bottom 66>[[Dilation and curettage|Dilation and Curettage]]<left 50><right 75>[[Intact dilation and extraction|Intact D&X]]<left 7.5><right 22.5><top 74><bottom 84>[[Mifepristone]]<left 40><right 75>[[Induced miscarriage|Induced Miscarriage]]<left 0><right 30><background-color #b7e690><top 90><bottom 100>[[first trimester|1st Trimester]]: 0-12 weeks<left 30><right 70><background-color #dfe988>[[second trimester|2nd Trimester]]: 12-28 weeks<left 70><right 100><background-color #e9c788>[[third trimester|3rd Trimester]]: 28-40 weeks}}

In this example:

  • Border-width 0 0 0 1px is applied to two divs at 30 and 70 which inherit the default 0 and 100 top and bottom values. These include a   each because if there is no text at all nothing is drawn (so you can specify multiple tags without drawing a div every time).
  • The next two divs are completely specified on top, bottom, left, right. The background-color sets the shade of each box. Wikilinks are brought in with the text itself.
  • Each row uses a <top> and <bottom> that carries on to several divs in the row until they are reset.

local p={}

function p.main(frame)
   local args=frame.args or {}
   local parent=frame.getParent(frame) or {}
   local pargs=parent.args or {}
   local textinput=args[1] or pargs[1] or ""
   local nowiki=args.nowiki or pargs.nowiki or nil
   local totalwidth=args.width or pargs.width or 220
   local totalheight=args.height or pargs.height or 200
   local debug=args.debug or pargs.debug
   local debuglog=""
    --- Allow searching of all text to end with:
   textinput=textinput.."<Module:Block diagram internal end token:END>"
    --- Give all RECOGNIZED markup a consistent searchable string
    --- more styling should be added; seeking a first proof of concept now
   local taglist={'left','top','right','bottom','color','background-color','text-align','vertical-align','vcentertext','border-style','border-color','border-width'}
   for i,v in pairs(taglist) do
       local vn=mw.ustring.gsub(v,"%-","") --- remove dashes from standard html attribute names to allow internal use
       local vs=mw.ustring.gsub(v,"%-","%-") -- escape those hyphens for pattern search
       textinput=mw.ustring.gsub(textinput,"<"..vs.."%s*([^>]*)>","<Module:Block diagram internal "..vn.." token:%1>")
       debuglog=debuglog..v..vs..vn..textinput
   end
   prowl=mw.ustring.gmatch(textinput,"(.-)<Module:Block diagram internal (%S+) token:([^>]*)>")
   local tableoutput={}
   local text,tag,value
   local default={}
   default['left']=0
   default['right']=100
   default['top']=0
   default['bottom']=100
   default['borderstyle']='solid'
   default['borderwidth']='1px'
   default['bordercolor']='black'
   default['color']='black'
   default['backgroundcolor']='white' -- elements should usually block elements behind them, like grid lines
   default['textalign']='center'
   default['verticalalign']='middle' -- pseudo html value, but this needs a special hack to work
   default['vcentertext']=''
   for i,j in pairs(default) do
      _G[i]=j
      debuglog=debuglog..i..j
   end
   repeat
      text,tag,value = prowl(textinput)
      debuglog=debuglog..(text or "nil")..(tag or "nil")
      if not tag then return debuglog end
      if (text or "")~="" then
         table.insert(tableoutput,'<div style="position:absolute;top:')
         table.insert(tableoutput,top)
         table.insert(tableoutput,'%;bottom:')
         table.insert(tableoutput,100-bottom)
         table.insert(tableoutput,'%;left:')
         table.insert(tableoutput,left)
         table.insert(tableoutput,'%;right:')
         table.insert(tableoutput,100-right)
         table.insert(tableoutput,'%;border-style:')
         table.insert(tableoutput,borderstyle)
         table.insert(tableoutput,';border-width:')
         table.insert(tableoutput,borderwidth)
         table.insert(tableoutput,';border-color:')
         table.insert(tableoutput,bordercolor)
         table.insert(tableoutput,';color:')
         table.insert(tableoutput,color)
         table.insert(tableoutput,';background-color:')
         table.insert(tableoutput,backgroundcolor)
         table.insert(tableoutput,';">')
         if textalign~='center' then
             table.insert(tableoutput,';text-align:'..textalign)
         end
         if verticalalign=='top' then
             table.insert(tableoutput,text)
         else
             table.insert(tableoutput,'{{vertical center|1=')
             table.insert(tableoutput,text)
             if vcentertext then table.insert(tableoutput,'|3='..vcentertext) end
             table.insert(tableoutput,'}}')
         end
         table.insert(tableoutput,'</div>')
      end
      _G[tag]=value or default[tag]
   until tag=="end"
   local textoutput=table.concat(tableoutput)
   textoutput='<div style="position:relative;text-align:center;top:0;left:0;width:'..totalwidth..'px;height:'..totalheight..'px;">'..textoutput..'</div>'
   if nowiki then textoutput=frame:preprocess("<pre><nowiki>"..textoutput.."</nowiki></pre>") else textoutput=frame:preprocess(textoutput) end
   if debug then textoutput=textoutput..debuglog end
   return textoutput
end

return p