前言

上一篇 JS元件系列——自己動手封裝bootstrap-treegrid元件 博主自己動手封裝了下treegrid的功能,但畢竟那個元件只是一個單獨針對樹形表格做的,適用性還比較有限。關注博主的小夥伴應該知道,博主的部落格裡面寫了很多bootstrapTable的擴充套件,今天打算在直接在bootstrapTable的基礎上擴充套件一個treegrid的功能,很多長期關注博主部落格的小夥伴一直在問我怎麼在bootstrapTable裡面直接使用treegrid的功能,所以今天還是帶來點福利。有興趣的可以捧個人場!

本文原創地址:JS元件系列——自己動手擴充套件BootstrapTable的trefgrid功能

一、效果預覽

全部摺疊

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

展開一級

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

全部展開

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

JS元件系列——自己動手擴充套件BootstrapTable的treegrid功能

二、程式碼示例

怎麼樣?效果還行吧。給出js的原始碼供大家參考。

function

$

{

‘use strict’

var

sprintf

=

function

str

{

var

args

=

arguments

flag

=

true

i

=

1

str

=

str

replace

/%s/g

function

()

{

var

arg

=

args

i

++

];

if

typeof

arg

===

‘undefined’

{

flag

=

false

return

‘’

}

return

arg

});

return

flag

str

‘’

};

var

getFieldIndex

=

function

columns

field

{

var

index

=

-

1

$

each

columns

function

i

column

{

if

column

field

===

field

{

index

=

i

return

false

}

return

true

});

return

index

};

var

calculateObjectValue

=

function

self

name

args

defaultValue

{

var

func

=

name

if

typeof

name

===

‘string’

{

var

names

=

name

split

‘。’

);

if

names

length

>

1

{

func

=

window

$

each

names

function

i

f

{

func

=

func

f

];

});

}

else

{

func

=

window

name

];

}

}

if

typeof

func

===

‘object’

{

return

func

}

if

typeof

func

===

‘function’

{

return

func

apply

self

args

);

}

if

func

&&

typeof

name

===

‘string’

&&

sprintf

apply

this

name

]。

concat

args

)))

{

return

sprintf

apply

this

name

]。

concat

args

));

}

return

defaultValue

};

var

getItemField

=

function

item

field

{

var

value

=

item

if

typeof

field

!==

‘string’

||

item

hasOwnProperty

field

))

{

return

item

field

];

}

var

props

=

field

split

‘。’

);

for

var

p

in

props

{

value

=

value

props

p

]];

}

return

value

};

var

getParent

=

function

node

source

field

{

var

data

=

[];

var

items

=

$

grep

source

function

item

index

{

return

node

ParentId

==

item

field

];

});

$

each

items

function

index

item

{

data

splice

0

0

item

);

var

child

=

getParent

item

source

field

);

$

each

child

function

i

n

{

data

splice

0

0

n

);

});

});

return

data

};

var

getChild

=

function

node

source

field

{

var

data

=

[];

var

items

=

$

grep

source

function

item

index

{

return

item

ParentId

==

node

field

];

});

$

each

items

function

index

item

{

data

push

item

);

var

child

=

getChild

item

source

field

);

$

each

child

function

i

n

{

data

push

n

);

});

});

return

data

};

//呼叫bootstrapTable元件的構造器得到物件

var

BootstrapTable

=

$

fn

bootstrapTable

Constructor

_initData

=

BootstrapTable

prototype

initData

_initPagination

=

BootstrapTable

prototype

initPagination

_initBody

=

BootstrapTable

prototype

initBody

//重寫bootstrapTable的initData方法

BootstrapTable

prototype

initData

=

function

()

{

_initData

apply

this

Array

prototype

slice

apply

arguments

));

var

that

=

this

if

that

options

treeView

&&

this

data

length

>

0

{

var

rows

=

[];

var

roots

=

$

grep

this

data

function

row

index

{

return

row

Level

==

that

options

treeRootLevel

});

$

each

roots

function

index

item

{

rows

push

item

);

var

child

=

getChild

item

that

data

that

options

treeId

);

$

each

child

function

i

n

{

if

that

options

treeCollapseAll

{

n

hidden

=

true

}

rows

push

n

);

});

});

that

options

data

=

that

data

=

rows

}

};

//重寫bootstrapTable的initPagination方法

BootstrapTable

prototype

initPagination

=

function

()

{

//理論情況下,treegrid是不支援分頁的,所以預設分頁引數為false

this

options

pagination

=

false

//呼叫“父類”的“虛方法”

_initPagination

apply

this

Array

prototype

slice

apply

arguments

));

};

//重寫bootstrapTable的initBody方法

BootstrapTable

prototype

initBody

=

function

fixedScroll

{

var

that

=

this

html

=

[],

data

=

this

getData

();

this

trigger

‘pre-body’

data

);

this

$body

=

this

$el

find

‘tbody’

);

if

this

$body

length

{

this

$body

=

$

‘’

)。

appendTo

this

$el

);

}

if

this

options

pagination

||

this

options

sidePagination

===

‘server’

{

this

pageFrom

=

1

this

pageTo

=

data

length

}

for

var

i

=

this

pageFrom

-

1

i

<

this

pageTo

i

++

{

var

key

item

=

data

i

],

style

=

{},

csses

=

[],

data_

=

‘’

attributes

=

{},

htmlAttributes

=

[];

if

item

hidden

continue

style

=

calculateObjectValue

this

options

this

options

rowStyle

item

i

],

style

);

if

style

&&

style

css

{

for

key

in

style

css

{

csses

push

key

+

‘: ’

+

style

css

key

]);

}

}

attributes

=

calculateObjectValue

this

options

this

options

rowAttributes

item

i

],

attributes

);

if

attributes

{

for

key

in

attributes

{

htmlAttributes

push

sprintf

‘%s=“%s”’

key

escapeHTML

attributes

key

])));

}

}

if

item

_data

&&

$

isEmptyObject

item

_data

))

{

$

each

item

_data

function

k

v

{

if

k

===

‘index’

{

return

}

data_

+=

sprintf

‘ data-%s=“%s”’

k

v

);

});

}

html

push

sprintf

‘ %s’

htmlAttributes

join

‘ ’

)),

sprintf

‘ id=“%s”’

$

isArray

item

undefined

item

_id

),

sprintf

‘ class=“%s”’

style

classes

||

$

isArray

item

undefined

item

_class

)),

sprintf

‘ data-index=“%s”’

i

),

sprintf

‘ data-uniqueid=“%s”’

item

this

options

uniqueId

]),

sprintf

‘%s’

data_

),

‘>’

);

if

this

options

cardView

{

html

push

sprintf

‘’

this

header

fields

length

));

}

if

this

options

cardView

&&

this

options

detailView

{

html

push

‘’

sprintf

this

options

iconsPrefix

this

options

icons

detailOpen

),

‘’

);

}

$

each

this

header

fields

function

j

field

{

var

text

=

‘’

value

=

getItemField

item

field

),

type

=

‘’

cellStyle

=

{},

id_

=

‘’

class_

=

that

header

classes

j

],

data_

=

‘’

rowspan_

=

‘’

title_

=

‘’

column

=

that

columns

getFieldIndex

that

columns

field

)];

if

column

visible

{

return

}

style

=

sprintf

‘style=“%s”’

csses

concat

that

header

styles

j

])。

join

‘; ’

));

value

=

calculateObjectValue

column

that

header

formatters

j

],

value

item

i

],

value

);

if

item

‘_’

+

field

+

‘_id’

])

{

id_

=

sprintf

‘ id=“%s”’

item

‘_’

+

field

+

‘_id’

]);

}

if

item

‘_’

+

field

+

‘_class’

])

{

class_

=

sprintf

‘ class=“%s”’

item

‘_’

+

field

+

‘_class’

]);

}

if

item

‘_’

+

field

+

‘_rowspan’

])

{

rowspan_

=

sprintf

‘ rowspan=“%s”’

item

‘_’

+

field

+

‘_rowspan’

]);

}

if

item

‘_’

+

field

+

‘_title’

])

{

title_

=

sprintf

‘ title=“%s”’

item

‘_’

+

field

+

‘_title’

]);

}

cellStyle

=

calculateObjectValue

that

header

that

header

cellStyles

j

],

value

item

i

],

cellStyle

);

if

cellStyle

classes

{

class_

=

sprintf

‘ class=“%s”’

cellStyle

classes

);

}

if

cellStyle

css

{

var

csses_

=

[];

for

var

key

in

cellStyle

css

{

csses_

push

key

+

‘: ’

+

cellStyle

css

key

]);

}

style

=

sprintf

‘style=“%s”’

csses_

concat

that

header

styles

j

])。

join

‘; ’

));

}

if

item

‘_’

+

field

+

‘_data’

&&

$

isEmptyObject

item

‘_’

+

field

+

‘_data’

]))

{

$

each

item

‘_’

+

field

+

‘_data’

],

function

k

v

{

if

k

===

‘index’

{

return

}

data_

+=

sprintf

‘ data-%s=“%s”’

k

v

);

});

}

if

column

checkbox

||

column

radio

{

type

=

column

checkbox

‘checkbox’

type

type

=

column

radio

‘radio’

type

text

=

that

options

cardView

‘’

+

sprintf

‘ data-index=“%s”’

i

+

sprintf

‘ name=“%s”’

that

options

selectItemName

+

sprintf

‘ type=“%s”’

type

+

sprintf

‘ value=“%s”’

item

that

options

idField

])

+

sprintf

‘ checked=“%s”’

value

===

true

||

value

&&

value

checked

‘checked’

undefined

+

sprintf

‘ disabled=“%s”’

column

checkboxEnabled

||

value

&&

value

disabled

‘disabled’

undefined

+

‘ />’

that

header

formatters

j

&&

typeof

value

===

‘string’

value

‘’

that

options

cardView

‘’

]。

join

‘’

);

item

that

header

stateField

=

value

===

true

||

value

&&

value

checked

);

}

else

{

value

=

typeof

value

===

‘undefined’

||

value

===

null

that

options

undefinedText

value

var

indent

icon

if

that

options

treeView

&&

column

field

==

that

options

treeField

{

var

indent

=

item

Level

==

that

options

Level

‘’

sprintf

item

Level

-

that

options

treeRootLevel

*

15

);

var

child

=

$

grep

data

function

d

i

{

return

d

ParentId

==

item

that

options

treeId

&&

d

hidden

});

icon

=

sprintf

child

length

>

0

that

options

expandIcon

that

options

collapseIcon

);

//icon = sprintf(‘’, child。length > 0 ? that。options。expandIcon : “”);

}

text

=

that

options

cardView

that

options

showHeader

sprintf

%s

style

getPropertyFromOther

that

columns

‘field’

‘title’

field

))

‘’

sprintf

%s

value

),

]。

join

‘’

sprintf

id_

class_

style

data_

rowspan_

title_

),

indent

icon

value

‘’

]。

join

‘’

);

if

that

options

cardView

&&

that

options

smartDisplay

&&

value

===

‘’

{

text

=

‘’

}

}

html

push

text

);

});

if

this

options

cardView

{

html

push

‘’

);

}

html

push

‘’

);

}

if

html

length

{

html

push

‘’

sprintf

‘%s’

this

$header

find

‘th’

)。

length

this

options

formatNoMatches

()),

‘’

);

}

this

$body

html

html

join

‘’

));

if

fixedScroll

{

this

scrollTo

0

);

}

this

$body

find

‘> tr[data-index] > td’

)。

off

‘click dblclick’

)。

on

‘click dblclick’

function

e

{

var

$td

=

$

this

),

$tr

=

$td

parent

(),

item

=

that

data

$tr

data

‘index’

)],

index

=

$td

0

]。

cellIndex

field

=

that

header

fields

that

options

detailView

&&

that

options

cardView

index

-

1

index

],

column

=

that

columns

getFieldIndex

that

columns

field

)],

value

=

getItemField

item

field

);

if

$td

find

‘。detail-icon’

)。

length

{

return

}

that

trigger

e

type

===

‘click’

‘click-cell’

‘dbl-click-cell’

field

value

item

$td

);

that

trigger

e

type

===

‘click’

‘click-row’

‘dbl-click-row’

item

$tr

);

if

e

type

===

‘click’

&&

that

options

clickToSelect

&&

column

clickToSelect

{

var

$selectItem

=

$tr

find

sprintf

‘[name=“%s”]’

that

options

selectItemName

));

if

$selectItem

length

{

$selectItem

0

]。

click

();

}

}

});

this

$body

find

‘> tr[data-index] > td > 。detail-icon’

)。

off

‘click’

)。

on

‘click’

function

()

{

debugger

var

$this

=

$

this

),

$tr

=

$this

parent

()。

parent

(),

index

=

$tr

data

‘index’

),

row

=

data

index

];

if

$tr

next

()。

is

‘tr。detail-view’

))

{

$this

find

‘i’

)。

attr

‘class’

sprintf

‘%s %s’

that

options

iconsPrefix

that

options

icons

detailOpen

));

$tr

next

()。

remove

();

that

trigger

‘collapse-row’

index

row

);

}

else

{

$this

find

‘i’

)。

attr

‘class’

sprintf

‘%s %s’

that

options

iconsPrefix

that

options

icons

detailClose

));

$tr

after

sprintf

‘%s’

$tr

find

‘td’

)。

length

calculateObjectValue

that

options

that

options

detailFormatter

index

row

],

‘’

)));

that

trigger

‘expand-row’

index

row

$tr

next

()。

find

‘td’

));

}

that

resetView

();

});

this

$body

find

‘> tr[data-index] > td > 。tree-icon’

)。

off

‘click’

)。

on

‘click’

function

e

{

debugger

e

stopPropagation

();

var

$this

=

$

this

),

$tr

=

$this

parent

()。

parent

(),

index

=

$tr

data

‘index’

),

row

=

data

index

];

var

icon

=

$

this

);

var

child

=

getChild

data

index

],

data

that

options

treeId

);

$

each

child

function

i

c

{

$

each

that

data

function

index

item

{

if

item

that

options

treeId

==

c

that

options

treeId

])

{

item

hidden

=

icon

hasClass

that

options

expandIcon

);

that

uncheck

index

);

return

}

});

});

if

icon

hasClass

that

options

expandIcon

))

{

icon

removeClass

that

options

expandIcon

)。

addClass

that

options

collapseIcon

);

}

else

{

icon

removeClass

that

options

collapseIcon

)。

addClass

that

options

expandIcon

);

}

that

options

data

=

that

data

that

initBody

true

);

});

this

$selectItem

=

this

$body

find

sprintf

‘[name=“%s”]’

this

options

selectItemName

));

this

$selectItem

off

‘click’

)。

on

‘click’

function

event

{

event

stopImmediatePropagation

();

var

$this

=

$

this

),

checked

=

$this

prop

‘checked’

),

row

=

that

data

$this

data

‘index’

)];

if

that

options

maintainSelected

&&

$

this

)。

is

‘:radio’

))

{

$

each

that

options

data

function

i

row

{

row

that

header

stateField

=

false

});

}

row

that

header

stateField

=

checked

if

that

options

singleSelect

{

that

$selectItem

not

this

)。

each

function

()

{

that

data

$

this

)。

data

‘index’

)][

that

header

stateField

=

false

});

that

$selectItem

filter

‘:checked’

)。

not

this

)。

prop

‘checked’

false

);

}

that

updateSelected

();

that

trigger

checked

‘check’

‘uncheck’

row

$this

);

});

$

each

this

header

events

function

i

events

{

if

events

{

return

}

if

typeof

events

===

‘string’

{

events

=

calculateObjectValue

null

events

);

}

var

field

=

that

header

fields

i

],

fieldIndex

=

$

inArray

field

that

getVisibleFields

());

if

that

options

detailView

&&

that

options

cardView

{

fieldIndex

+=

1

}

for

var

key

in

events

{

that

$body

find

‘tr’

)。

each

function

()

{

var

$tr

=

$

this

),

$td

=

$tr

find

that

options

cardView

‘。card-view’

‘td’

)。

eq

fieldIndex

),

index

=

key

indexOf

‘ ’

),

name

=

key

substring

0

index

),

el

=

key

substring

index

+

1

),

func

=

events

key

];

$td

find

el

)。

off

name

)。

on

name

function

e

{

var

index

=

$tr

data

‘index’

),

row

=

that

data

index

],

value

=

row

field

];

func

apply

this

e

value

row

index

]);

});

});

}

});

this

updateSelected

();

this

resetView

();

this

trigger

‘post-body’

);

};

//給元件增加預設引數列表

$

extend

$

fn

bootstrapTable

defaults

{

treeView

false

//treeView檢視

treeField

“id”

//treeView檢視欄位

treeId

“id”

treeRootLevel

0

//根節點序號

treeCollapseAll

false

//是否全部展開

collapseIcon

“glyphicon glyphicon-chevron-right”

//摺疊樣式

expandIcon

“glyphicon glyphicon-chevron-down”

//展開樣式

});

})(

jQuery

);

元件的使用如下:

1、首先引用這個js檔案。

2、然後初始化元件

$

‘#tb’

)。

bootstrapTable

({

url

ActionUrl

+

‘GetMenuList’

toolbar

‘#toolbar’

sidePagination

‘client’

pagination

false

treeView

true

treeId

“Id”

treeField

“Name”

treeRootLevel

1

clickToSelect

true

//collapseIcon: “glyphicon glyphicon-triangle-right”,//摺疊樣式

//expandIcon: “glyphicon glyphicon-triangle-bottom”//展開樣式

})

treeView:true表示啟用樹表格模式;

treeId:‘Id’表示每一行tree的id;

treeField:‘Name’表示要對那一列進行展開;

treeRootLevel:1表示樹根的級別。

還有一個地方需要注意,要建立記錄之間的父子級關係,必然後有一個ParentId的概念,所以在從後端返回的結果集裡面,每條記錄勢必有一個ParentId的屬性,如果是根節點,ParentId為null。比如我們後臺得到的結果集的json格式如下:

[{

Id

1

Name

“系統設定”

Url

null

ParentId

null

Level

1

CreateTime

null

Status

1

SortOrder

1

},

{

Id

2

Name

“選單管理”

Url

“/Systems/Menu/Index”

ParentId

1

Level

2

CreateTime

null

Status

1

},

{

Id

3

Name

“訂單管理”

Url

null

ParentId

null

Level

1

CreateTime

“2017-05-31 17:05:27”

},

{

Id

4

Name

“基礎資料”

Url

null

ParentId

null

Level

1

CreateTime

“2017-05-31 17:05:55”

},

{

Id

5

Name

“新增訂單”

Url

“/order/add”

ParentId

3

Level

2

CreateTime

“2017-05-31 17:07:03”

}]

三、元件需要完善的地方

上述封裝給大家提供一個擴充套件bootstrapTable元件treeview功能,還有很多地方需要完善,比如:

1、我們的葉子節點前面的圖示可以去掉;

2、增加展開所有、摺疊所有的功能;

3、Level欄位可以去掉,透過ParentId為null來確定根節點。

有興趣的小夥伴可以自己試試。

四、總結

至此本文就結束了,這篇針對上篇做了一個補充,使得我們可以根據專案的需求自己選擇用哪種方式,如果我們專案使用的是bootstrapTable作為資料展示的元件,可以考慮上述擴充套件;如果沒有使用bootstrapTable,可以試試上篇的元件。