Module:Navbox/doc

来自滚动的天空Wiki

本模块用于执行模板{{导航框}},用法详见模板说明。本模块是根据维基百科的Module:Navbox改写的,和维基百科的具有一定区别天壤之别

运作原理[编辑源代码]

对于模板,我们会将模板的参数(args)转换成可用于直接读取的数据(data),然后对数据进行迭代处理,以渲染整个表。

每个框表都是一个对象,其HTML对象存储在self.root中。每一个子框表又是一个新的对象,该对象会与其根对象(rootself)关联,因此子框表与根框表即有一定的独立性,又有一定的关联(子框表的listclass、liststyle取决于根框表而与子框表本身的设置无关,且子框表的列表和根框表的列表的奇偶性是一同处理的)。

index函数与newindex函数以及tnewindex函数[编辑源代码]

参见:模块:Util

index函数和newindex函数可以使得数据的处理变得更加方便。可以快速地求得一个表的嵌套域(即域中的域),同时避免无法索引空值(nil)而抛出的错误。

getkeys函数[编辑源代码]

这个函数以连字符为分隔拆分匹配出的数字组合,然后将每一个拆分出的字符串tostring。任何一个无法拆分都将返回nil。拆分后的数字将会夹着list和content被放入表中返回。

参数键的识别[编辑源代码]

本模块采用类似于正则表达式的“匹配模式”(patterns)来对参数(args)的键(key)进行解析(p.checkItem函数):

  1. 第一遍迭代识别以data开头,以数字结尾的参数键,并将其值解码为表作为子导航框数据。
  2. 第二遍迭代:
    • 对于name这一类单一的键,直接将其搬到data中。
    • 识别以list开头,其余部分为一个完整的键的键(其实这并没有用)。
    • 识别以title、above、below等开头(前缀)、其余部分(后缀)均为小写字母的键,这里的后缀通常是style、class、content或者为空,空和content是等价的。
    • 识别“小写字母(前缀)+数字组合+小写字母(后缀)”这样的键,前缀通常是group、list、title、above、below等,后缀同上一条。
      • 如果不识别,或后缀不为style、class、content及为空,并且前缀为list,后缀依然作为一个完整的参数键传入子导航框的数据(但函数还是使用根导航框的checkItem函数。
      • 对于单个数字的数字组合(比如1、2、3),如果前缀是group或list,相当于对该框表的特定的组或列进行定义,否则视为对特定位置的子框表的title、above、below等进行定义。
      • 对于多个数字的数字组合(用“-”隔开,比如1-4、2-3、5-1、2-3-2),则是对子框表进行定义。比如title2-3相当于第二列的子框表中的第三列的子框表的标题内容,list4-2表示第四列的子框表的第二列。
      • 如果定义了一个列,又定义了其列的子框表,则子框表内容优先。比如同时定义了list2-3和list2,则第二列为一个子框表,list2-3定义了这个子框表的第三列,list2则直接被忽略。

参数与数据的转换[编辑源代码]

本模块在渲染导航框前,需要先通过p.processArgs函数将对象内的参数(args)转换成数据(data)以供使用。

数据的转换过程中,需要用到上面提到过的index和newindex函数。例如,参数:

self.args = {
    above = "Above",
    below = "Below",
    ["below4-3"] = "Below4-3",
    bodyclass = "mobileplainbox",
    group1 = "Group1",
    group10 = "Group10",
    group2 = "Group2",
    ["group2-1"] = "Group2-1",
    ["group2-2"] = "Group2-2",
    ["group2-2style"] = "color:green;",
    group3 = "Group3",
    group4 = "Group4",
    ["group4-1"] = "Group4-1",
    ["group4-2"] = "Group4-2",
    ["group4-3"] = "Group4-3",
    ["group4-3-1"] = "Group4-3-1",
    ["group4-3-2"] = "Group4-3-2",
    group8 = "Group8",
    group9 = "Group9",
    list1 = "List1",
    list10 = "List10",
    ["list2-1"] = "List2-1",
    ["list2-2"] = "List2-2",
    ["list2-2style"] = "color:red;",
    list3 = "List3",
    ["list4-1"] = "List4-1",
    ["list4-2"] = "List4-2",
    ["list4-3"] = "List4-3(这个属性应该被忽略)",
    ["list4-3-1"] = "List4-3-1",
    ["list4-3-2"] = "List4-3-2",
    list8 = "List8",
    list9 = "List9",
    ["list9.5"] = "List9.5(小数是有效的,这在追加插入时尤其有用。)",
    name = "模块:Navbox",
    oddstyle = "color:navy;",
    title = "Title",
    title4 = "Title-4"
}

它应该被转换成:

self.data = {
  [1] = {
    group = { content = "Group1" },
    list = { content = "List1" },
  },
  [2] = {
    group = { content = "Group2" },
    list = {
      content = {
        [1] = {
          group = { content = "Group2-1" },
          list = { content = "List2-1" },
        },
        [2] = {
          group = { content = "Group2-2", style = "color:green;" },
          list = { content = "List2-2", style = "color:red;" },
        },
      },
    },
  },
  [3] = {
    group = { content = "Group3" },
    list = { content = "List3" },
  },
  [4] = {
    group = { content = "Group4" },
    list = {
      content = {
        [1] = {
          group = { content = "Group4-1" },
          list = { content = "List4-1" },
        },
        [2] = {
          group = { content = "Group4-2" },
          list = { content = "List4-2" },
        },
        [3] {
          group = { content = "Group4-3" },
          list = {
            content = {
              [1] = {
                group = { content = "Group4-3-1" },
                list = { content = "List4-3-1" },
              },
              [2] = {
                group = { content = "Group4-3-2" },
                list = { content = "List4-3-2" },
              },
              below = { content = "Below4-3" },
            },
          },
        },
        title = { content = "Title-4" },
      },
    },
  },
  [8] = {
    group = { content = "Group8" },
    list = { content = "List8" },
  },
  [9] = {
    group = { content = "Group9" },
    list = { content = "List9" },
  },
  [9.5] = {
    list = "List9.5(小数是有效的,这在追加插入时尤其有用。)"
  },
  [10] = {
    group = { content = "Group10" },
    list = { content = "List10" },
  },
  above = { content = "Above" },
  below = { content = "Below" },
  body = {
    class = "mobileplainbox",
  },
  group = { content = "Group8" },
  list = { content = "List4-3-2" },
  name = "模块:Navbox",
  odd = {
    style = "color:navy;",
  },
  title = { content = "Title" },
}

转换后,当前效果如下:

渲染[编辑源代码]

每一个框表对象都含有一个mw.html对象(该对象在代码中称为root),子框表也是如此。与维基百科版本不同的是,子框表的mw.html对象也是根框表的mw.html的一个子对象,最终一同被渲染成字符串,而不是先将子框表渲染成字符串再作为根框表的内容。

此版本的导航框是一个使用display: griddiv元素实现的,每一个单元格都是它的一个子元素。此外,导航框的标题单元格.navbox-title也是一个grid,以实现标题内容与导航栏、折叠按钮的排版。

此版本并没有对各元素硬编码什么样式,绝大多数样式都是通过CSS层叠样式表(参考MediaWiki:Gadget-navbox.css)实现的。由于本站在移动版视图使用和桌面版视图一致的Timeless皮肤,因此这些导航框在手机版可以正常显示。此外还默认设置了hlist类(暂时无法取消),这样,在需要使用到列表时不再需要设置listclass=hlist。

注意:渲染各列时,模块会先将所有含有list的列的键整合到一个序列表中,进行排序再依次渲染。这样可以避免由空缺时的渲染次序问题,比如如果指定了第1、2、4、5列而没有指定第3列,就一定会按照第1、2、4、5列的顺序渲染,而非1、2、5、4。