JavaScript:jerichoTab每次刷新

关于

由于使用了jerichoTab,每次切换到已经打开的Tab时,不会刷新页面(可能导致页面内容状态不一致等问题).

jerichoTab是一款模拟 firefox 标签页的插件, 通过丰富的API可以轻松的实现动态添加, 删除, 激活tab, 当tab页过多时会在左右两段增加滚动条…引用自:【地址

jQuery LOGO
image-2448

解决方案

只需加一句即可:

1
2
3
4
5
6
7
//activate the tag(orderKey is the tagGuid of each tab)
    setTabActive: function(orderKey) {
        var lastTab = $.fn.jerichoTab.tabpage.children('li').filter('.tab_selected');
        if (lastTab.length > 0) lastTab.swapTabEnable();
        $('#jerichotab_' + orderKey).loadData(true);//每次点击都刷新页面.[添加这一句即可每次点击页签都刷新内容]
        return $('#jerichotab_' + orderKey).swapTabEnable();
    },

附上完整JavaScript代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
/// <reference path="jquery.js"/>
/*
 * jerichotab
 * version: release-2.0.1 (05/13/2009)
 * @ jQuery v1.3.*
 *
 * Licensed under the GPL:
 *   http://gplv3.fsf.org
 *
 * Copyright 2008, 2009 Jericho [ thisnamemeansnothing[at]gmail.com ]
    ========================================
    #example:
       
    ========================================
    ========================================
    #API:
        #$.fn.initJerichoTab(Function):
                *renderTo(String): the tab render to('#sample')
                *uniqueId(String): the tab's id(It must be unique)
                *tabs(Array): the tabs will be initialized, whose items will be formated as follows:
                    {
                    **title(String): the tab title text
                    **iconImg(String): the tab icon that displayed from title text,
                    **closeable(Boolean): the switch that controls whether the tab can be closed (true as default)
                    }
                *activeTabIndex(Int): the tab you'd like to select after loading(0 as default)
                *contentHeight(Int): height of the content div tag
                *contentCss(Object): the same as style sheet
                *loadOnce(Boolean): the switch controls if load tab content at the first time(true as default)
                *tabWidth(Int): width of each tab(150 as default)
        #$.fn.jerichoTab.addTab(Function):
                *tabId(String); the unique tab Id(Unused, private)
                *tabFirer(JQuery Object): the object that makes tab shown in a special way
                *title(String): the tab title text
                *data(Object): the tab data to load,including:
                            **dataType:type of data,
                            **dataLink:data link
                                #example(must use as suited):
                                ##formtag:
                                    *dataType:'formtag',
                                    //***use the html tags in this page
                                    *dataLink:'#example'
                                    //***id of the tag you'd like to display in this tab
                                ##iframe:
                                    *dataType:'iframe',
                                    //***use the iframe to load another page
                                    *dataLink:''
                                    //***such as 'iframetemplates/iframe.htm'
                                    //***the relative url of the page you'd like to display in this tab,
                                    //***and jerichoTab will use an iframe to load it
                                ###html:
                                    *dataType:'html',
                                    //*** load data from html url
                                    *dataLink:''
                                    // *** the relative url of your html page
                                ##ajax:
                                *dataType:'ajax',
                                //***use ajax to load data with asynchronous operations
                                *dataLink:''
                                //*** yes,u can write down your ajax handler url and then jerichotab'll make a callback,
                                //*** so the responseText will be displayed in the content holder(u can use html tags in your server callback datas)
                *onLoadCompleted(Function): fired after the data has been loaded
                *iconImg(String): the tab icon that displayed below title text(relative to...),
                *closeable(Boolean): set whether the tab can be closed(true as default)
    ========================================
*/

//; (function($) {
$.extend($.fn, {
    initJerichoTab: function(setting) {
        var opts = $.fn.extend({
            //the container of jerichotab(is required,  a jQuery format selector String as '.container' or '#container')
            renderTo: null,
            //the unique id of jerichotab(is required and unique, not null)
            uniqueId: null,
            //format your tab data like this: [{title:'',iconImg:'',closeable:true},{title:'',iconImg:'',closeable:true}]
            //it's an Array...
            tabs: [],
            //when the jerichotab has been loaded, the tab you'ld like to display first(start at 0, and 0 as default)
            activeTabIndex: 0,
            //the style sheet of tab content
            contentCss: {
                'height': '500px'
            },
            //if you set this property as true, the data'll be loaded only at the first time when users click the tab
            //in other times jerichotab only swich it's css(display property) from 'none' to 'block'
            loadOnce: true,
            //the tab width (150 as default)
            tabWidth: 110,
            //set an ajaxload effect, jerichotab has provided two choices: 'usebg' | 'righttag'
            //'usebg': control if set a big loading gif in the contentholder
            //'righttag': this will set a small loading gif in the right top of contentholder
            loader: 'righttag',
            //两边滑块宽度
            slidersWidth: 19,
            //标题高度
            titleHeight: 26
        }, setting);
        //initialize the jerichotab
        function createJerichoTab() {
            //make sure that a container and uniqueId were provided
            if (opts.renderTo == null) { alert('you must set the \'renderTo\' property\r\t--JeirchoTab'); return; }
            if (opts.uniqueId == null) { alert('you must set the \'uniqueId\' property\r\t--JeirchoTab'); return; }
            if ($('#' + opts.uniqueId).length > 0) { alert('you must set the \'uniqueId\' property as unique\r\t--JeirchoTab'); return; }
            //the jerichotab html tree:
            /* <div class="jericho_tab">
            <div class="tab_pages" >
            <div class="tabs">
            <ul /> ###tabpages here
            </div>
            </div>
            <div class="tab_content">
            <div id="jerichotab_contentholder" class="content" /> ###tabcontents here
            </div>
            </div>
            */
            var jerichotab = $('<div id="'+opts.uniqueId+'" class="jericho_tab"><div class="tab_pages" ><div class="tabs"><ul /></div></div><div class="tab_content"><div id="jerichotab_contentholder" class="content" /></div></div>')
                                            .appendTo($(opts.renderTo));
           
            //apply contentcss to the contentholder
            $('.tab_content>.content', jerichotab).css(opts.contentCss);
           
            //fill data
            $.fn.jerichoTab = {
                master: jerichotab,
                tabWidth: opts.tabWidth,
                tabPageWidth: $('.tab_pages', jerichotab).width(),
                slidersWidth: opts.slidersWidth,
                loader: opts.loader,
                loadOnce: opts.loadOnce,
                tabpage: $('.tab_pages>.tabs>ul', jerichotab),
                addTab: function(tabsetting) {
                    //set as the unique tab id and tabFirer tag
                    tagGuid = (typeof tagGuid == 'undefined' ? 0 : tagGuid + 1);
                    var curIndex = tagGuid;
                    //this function will be open to all users for them to add tab at any time
                    var ps = $.fn.extend({
                        //if there is a DOM that cause the tab to be added to tabpages,
                        //you should pass it to jerichotab, in which way tab'll only be activated when
                        //user click the DOM next time
                        tabFirer: null,
                        title: '新增页签'+(curIndex+1),
                        //the dataType and dataLink were suited as:
                        //1.formtag:
                        //   dataType:'formtag',
                        //                  --use the html tags in this page
                        //   dataLink:'#example'
                        //                  --id of the tag you'ld like to display in this tab
                        //2.iframe:
                        //   dataType:'iframe',
                        //                  --use the iframe to load another page
                        //   dataLink:''
                        //                  --such as 'iframetemplates/iframe.htm', set
                        //                  --the relative url of the page u'ld like to display in this tab,
                        //                  --and jerichoTab will use an iframe to load it
                        //3.html:
                        //   dataType:'html',
                        //                  --load html tags from a url
                        //   dataLink:''
                        //                  --the relative url of your html page
                        //4.ajax:
                        //   dataType:'ajax',
                        //                  --use the ajax to load datas with asynchronous operations
                        //    dataLink:''
                        //                  --yes,u can write down your ajax handler url and jerichotab'll make a callback,
                        //                  --so the responseText will be displayed in the content holder(u can use html tags in your server callback datas)
                        data: { dataType: '', dataLink: '' },
                        //set the tab icon of each(relative to...)
                        iconImg: '',
                        //whether this tab can be closed(ture as default)
                        closeable: true,
                        //this function will be fired after all data has been loaded
                        onLoadCompleted: null,
                        // the tab's name
                        name:''
                    }, tabsetting);
                    //window.console && console.log('%o', tabsetting);
                    //check whether the tabFirer exists or not, and that it has an attribute['jerichotabindex'], then set the tab that tabFirer was connected activated
                    //otherwise attach the jerichotabindex' attribute
                    if (ps.tabFirer != null) {
                        var jerichotabindex = ps.tabFirer.attr('jerichotabindex');
                        if (typeof jerichotabindex != 'undefined' && $('#jerichotab_' + jerichotabindex).length > 0)
                            return $.fn.setTabActive(jerichotabindex).adaptSlider().loadData();
                        ps.tabFirer.attr('jerichotabindex', curIndex);
                    }
                    // set name
                    if(ps.name == ''){
                        ps.name = ps.title;
                    }
                    //newTab html tree:
                    /*
                    <li>
                    <div class="tab_left" >
                    <div class="tab_icon" />
                    <div class="tab_text" >JerichoTab</div>
                    <div class="tab_close">
                    <a href="javascript:void(0)" title="Close">&nbsp;</a>
                    </div>
                    </div>
                    <div class="tab_right">&nbsp;</div>
                    </li>
                    */
                    /*var newTab = $('<li class="jericho_tabs tab_selected" style="width:0px"  id="jerichotab_' + curIndex + '" dataType="' + ps.data.dataType + '" dataLink="' + ps.data.dataLink + '">' +
                                        '<div class="tab_left"  style="width:' + (opts.tabWidth - 5) + 'px"  >' +
                                            (ps.iconImg == '' ? '' : '<div class="tab_icon" style="' + 'background-image:url(' + ps.iconImg + ')' + '">&nbsp;</div>') +
                                            '<div class="tab_text" title="' + ps.title + '"  style="width:' + (opts.tabWidth - 45 + (ps.iconImg == '' ? 25 : 0)) + 'px"  >' + ps.title.cut(opts.tabWidth / 10 - 1) + '</div>  ' +
                                            '<div class="tab_close">' + (ps.closeable ? '<a href="javascript:" title="关闭">&nbsp;</a>' : '') + '</div>' +
                                        '</div>' +
                                        '<div class="tab_right">&nbsp;</div>' +
                                    '</li>')*/
                    var newTab = $('<li name="'+ps.name+'" class="jericho_tabs tab_selected" style="width:0px"  id="jerichotab_' + curIndex + '" dataType="' + ps.data.dataType + '" dataLink="' + ps.data.dataLink + '">' +
                            '<div class="tab_left"  style="width:' + (opts.tabWidth - 5) + 'px"  >' +
                                (ps.iconImg == '' ? '' : '<div class="tab_icon" style="' + 'background-image:url(' + ps.iconImg + ')' + '">&nbsp;</div>') +
                                '<div class="tab_text" title="' + ps.title + '"  style="width:' + (opts.tabWidth - 45 + (ps.iconImg == '' ? 25 : 0)) + 'px"  >' + ps.title.cut(opts.tabWidth / 10 - 1) + '</div>  ' +
                                '<div class="tab_close">' + (ps.closeable ? '<a href="javascript:" title="关闭">&nbsp;</a>' : '') + '</div>' +
                            '</div>' +
                            '<div class="tab_right">&nbsp;</div>' +
                        '</li>').appendTo($.fn.jerichoTab.tabpage).css('opacity', '0').applyHover()
                              .applyCloseEvent().animate({ 'opacity': '1', width: opts.tabWidth }, 100, function() {
                        $.fn.setTabActive(curIndex);
                    });
                    //use an Array named "tabHash" to restore the tab information
                    tabHash = (typeof tabHash == 'undefined' ? [] : tabHash);
                    tabHash.push({
                        index: curIndex,
                        tabFirer: ps.tabFirer,
                        tabId: 'jerichotab_' + curIndex,
                        holderId: 'jerichotabholder_' + curIndex,
                        iframeId: 'jerichotabiframe_' + curIndex,
                        onCompleted: ps.onLoadCompleted
                    });
                    return newTab.applySlider();
                },
                closeCurrentTab: function(tabsetting) {
                    $('.tab_selected .tab_close>a').click();
                    /*var ps = $.fn.extend({
                        name:'',
                        activeTabName:'',
                        isReaload: false
                    }, tabsetting);
                   
                    $.fn.jerichoTab.tabpage.children('li[name='+ps.name+']').remove();
                   
                    var isLoad = 0;
                    if(ps.activeTabName != ''){
                        var lis = $.fn.jerichoTab.tabpage.children('li');
                        for(var i=0;i<lis.size();i++){
                            if(lis.eq(i).attr('name')==ps.activeTabName){
                                $.fn.setTabActive(i).loadData(ps.isReaload);
                                isLoad = 1;
                                break;
                            }
                        }
                    }
                    if(isLoad==0){
                        $.fn.setTabActive(0).loadData(ps.isReaload);
                    }*/
                   
                },
            };
            $.each(opts.tabs, function(i, n) {
                $.fn.jerichoTab.addTab(n);
            });
            try{
                if (tabHash.length == 0)
                    jerichotab.css({ 'display': 'none' });
            }catch(e){ }
        }
        createJerichoTab();
        $.fn.setTabActive(opts.activeTabIndex).loadData();
        $.fn.jerichoTab.resize = function() {
            $.fn.jerichoTab.tabPageWidth = $(".tab_pages", $.fn.jerichoTab.master).width() - (($(".jericho_slider").length > 0) ? ($.fn.jerichoTab.slidersWidth * 2) : 0);
            $(".tabs", $.fn.jerichoTab.master).width($.fn.jerichoTab.tabPageWidth).applySlider().adaptSlider();
            var fixHeight = -2;
            //if (Metronic.isIE8()){
            //  fixHeight = 25;
            //}
            $('#jerichotab_contentholder').height($(opts.renderTo).height() - opts.titleHeight - 5 - fixHeight);
            $(".jericho_tab iframe").height($(".jericho_tab").parent().height() - opts.titleHeight - fixHeight);
        };
        $(window).resize(function() {
            $.fn.jerichoTab.resize();
        })
        //window.console && console.log('width :' + $.fn.jerichoTab.tabpage.width());
    },
    //activate the tag(orderkey is the tab order, start at 1)
    setTabActiveByOrder: function(orderKey) {
        var lastTab = $.fn.jerichoTab.tabpage.children('li').filter('.tab_selected');
        if (lastTab.length > 0) lastTab.swapTabEnable();
        return $('#jericho_tabs').filter(':nth-child(' + orderKey + ')').swapTabEnable();
    },
    //activate the tag(orderKey is the tagGuid of each tab)
    setTabActive: function(orderKey) {
        var lastTab = $.fn.jerichoTab.tabpage.children('li').filter('.tab_selected');
        if (lastTab.length > 0) lastTab.swapTabEnable();
        $('#jerichotab_' + orderKey).loadData(true);//每次点击都刷新页面.
        return $('#jerichotab_' + orderKey).swapTabEnable();
    },
    addEvent: function(e, h) {
        var target = this.get(0);
        if (target.addEventListener) {
            target.addEventListener(e, h, false);
        } else if (target.attachEvent) {
            target.attachEvent('on' + e, h);
        }
    },
    //create an iframe in the contentholder to load pages
    buildIFrame: function(src) {
        return this.each(function() {
            var onComleted = null, jerichotabiframe = '';
            for (var tab in tabHash) {
                if (tabHash[tab].holderId == $(this).attr('id')) {
                    onComleted = tabHash[tab].onCompleted;
                    jerichotabiframe = tabHash[tab].iframeId;
                    break;
                }
            }
            src += (src.indexOf('?') == -1 ? '?' : '&') + 'tabPageId=' + jerichotabiframe;
            var iframe = $('<iframe id="' + jerichotabiframe + '" name="' + jerichotabiframe + '" src="' + src + '" frameborder="0" scrolling="auto" />')
                            .css({ width: '100%', height: $(this).parent().height(), border: 0 }).appendTo($(this));
            //add a listener to the load event
            $('#' + jerichotabiframe).addEvent('load', function() {
                //if onComlete(Function) is not null, then release it
                !!onComleted ? onComleted(arguments[1]) : true;
                $.fn.removeLoader();
            });
        });
    },
    //load data from dataLink
    //use the following function after each tab was activated
    loadData: function(flag) {
        return this.each(function() {
            $('.jericho_tab .tab_selected').css('background-color', $('body').css('background-color'));
            //show ajaxloader first
            $('#jerichotab_contentholder').showLoader();
            var onComleted = null, holderId = '', tabId = '';
            //search information in tabHash
            for (var tab in tabHash) {
                if (tabHash[tab].tabId == $(this).attr('id')) {
                    onComleted = tabHash[tab].onCompleted;
                    holderId = '#' + tabHash[tab].holderId;
                    tabId = '#' + tabHash[tab].tabId;
                    break;
                }
            }
            var dataType = $(this).attr('dataType');
            var dataLink = $(this).attr('dataLink');
            //if dataType was undefined, nothing will be done
            if (typeof dataType == 'undefined' || dataType == '' || dataType == 'undefined') { removeLoading(); return; }
            //hide the rest contentholders
            $('#jerichotab_contentholder').children('div[class=curholder]').attr('class', 'holder').css({ 'display': 'none' });
            var holder = $(holderId);
            if (holder.length == 0) {
                //if contentholder DOM hasn't been created, create it immediately
                holder = $('<div class="curholder" id="' + holderId.replace('#', '') + '" />').appendTo($('#jerichotab_contentholder'));
                //load data into holder
                load(holder);
            }
            else {
                holder.attr('class', 'curholder').css({ 'display': 'block' });
                if ($.fn.jerichoTab.loadOnce && !flag){
                    removeLoading();
                } else {
                    holder.html('');
                    load(holder);
                }
            }

            function load(c) {
                switch (dataType) {
                    case 'formtag':
                        //clone html DOM elements in the page
                        $(dataLink).css('display', 'none');
                        var clone = $(dataLink).clone(true).appendTo(c).css('display', 'block');
                        removeLoading(holder);
                        break;
                    case 'html':
                        //load HTML from page
                        holder.load(dataLink + '?t=' + Math.floor(Math.random()), function() {
                            removeLoading(holder);
                        });
                        break;
                    case 'iframe':
                        //use iframe to load a website
                        holder.buildIFrame(dataLink, holder);
                        break;
                    case 'ajax':
                        //load a remote page using an HTTP request
                        $.ajax({
                            url: dataLink,
                            data: { t: Math.floor(Math.random()) },
                            error: function(r) {
                                holder.html('数据加载失败!');
                                removeLoading(holder);
                            },
                            success: function(r) {
                                holder.html(r);
                                removeLoading(holder);
                            }
                        });
                        break;
                }
            }
            function removeLoading(h) {
                !!onComleted ? onComleted(h) : true;
                $.fn.removeLoader();
            }
        });
    },
    //attach the slider event to every tab,
    //so users can slide the tabs when there are too much tabs
    attachSliderEvent: function() {
        return this.each(function() {
            var me = this;
            $(me).hover(function() {
                $(me).swapClass('jericho_slider' + $(me).attr('pos') + '_enable', 'jericho_slider' + $(me).attr('pos') + '_hover');
            }, function() {
                $(me).swapClass('jericho_slider' + $(me).attr('pos') + '_hover', 'jericho_slider' + $(me).attr('pos') + '_enable');
            }).mouseup(function() {
                //filter the sliders in order to prevent users from sliding`
                if ($(me).is('[slide=no]')) return;
                //get the css(left) of tabpage(ul elements)
                var offLeft = parseInt($.fn.jerichoTab.tabpage.css('left'));
                //the max css(left) of tabpage
                var maxLeft = tabHash.length * $.fn.jerichoTab.tabWidth - $.fn.jerichoTab.tabPageWidth + ($.fn.jerichoTab.slidersWidth * 2);
                switch ($(me).attr('pos')) {
                    case 'left':
                        //slide to the left side
                        if (offLeft + $.fn.jerichoTab.tabWidth < 0)
                            $.fn.jerichoTab.tabpage.animate({ left: offLeft + $.fn.jerichoTab.tabWidth }, 100);
                        else
                            $.fn.jerichoTab.tabpage.animate({ left: 0 }, 100, function() {
                                $(me).attr({ 'slide': 'no', 'class': 'jericho_sliders jericho_sliderleft_disable' });
                            });
                        $('.jericho_sliders[pos=right]').attr({ 'slide': 'yes', 'class': 'jericho_sliders jericho_sliderright_enable' });
                        break;
                    case 'right':
                        //slide to the right side
                        if (offLeft - $.fn.jerichoTab.tabWidth > -maxLeft)
                            $.fn.jerichoTab.tabpage.animate({ left: offLeft - $.fn.jerichoTab.tabWidth }, 100);
                        else
                            $.fn.jerichoTab.tabpage.animate({ left: -maxLeft }, 100, function() {
                                $(me).attr({ 'slide': 'no', 'class': 'jericho_sliders jericho_sliderright_disable' });
                            });
                        $('.jericho_sliders[pos=left]').attr({ 'slide': 'yes', 'class': 'jericho_sliders jericho_sliderleft_enable' });
                        break;
                }
            });
        });
    },
    //create or activate the slider to tabpage
    applySlider: function() {
        return this.each(function() {
            if (typeof tabHash == 'undefined' || tabHash.length == 0) return;
            //get the offwidth of tabpage
            var offWidth = tabHash.length * $.fn.jerichoTab.tabWidth - $.fn.jerichoTab.tabPageWidth + ($.fn.jerichoTab.slidersWidth * 2);
            if (tabHash.length > 0 && offWidth > 0) {
                //make sure that the parent Div of tabpage was fixed(position:relative)
                //so jerichotab can control the display position of tabpage by using 'left'
                $.fn.jerichoTab.tabpage.parent().css({ width: $.fn.jerichoTab.tabPageWidth - ($.fn.jerichoTab.slidersWidth * 2) });
                //auto grow the tabpage(ul) width and reset 'left'
                $.fn.jerichoTab.tabpage.css({ width: offWidth + $.fn.jerichoTab.tabPageWidth - ($.fn.jerichoTab.slidersWidth * 2) })
                        .animate({ left: -offWidth }, 0, function() {
                    //append 'jerichosliders' to the tabpageholder if 'jerichoslider' has't been added
                    if ($('.jericho_sliders').length <= 0) {
                        var s = 'onclick="if(document.selection && document.selection.empty) {document.selection.empty();}else if(window.getSelection) {var sel = window.getSelection();sel.removeAllRanges();}"';
                        $.fn.jerichoTab.tabpage.parent()
                            .before($('<div class="jericho_sliders jericho_sliderleft_enable" slide="yes" pos="left" '+s+'></div>'));
                        $.fn.jerichoTab.tabpage.parent()
                            .after($('<div class="jericho_sliders jericho_sliderright_disable" pos="right" slide="yes" '+s+'></div>'));
                        $('.jericho_sliders').attachSliderEvent();
                    }
                    //$('.jericho_sliders').adaptSlider();
                });
            }
            else if (tabHash.length > 0 && offWidth <= 0) {
                //remove 'jerichosliders' whether the tabs were not go beyond the capacity of tabpageholder
                $('.jericho_sliders').remove();
                $.fn.jerichoTab.tabpage.parent().css({ width: $.fn.jerichoTab.tabPageWidth });
                $.fn.jerichoTab.tabpage.css({ width: -offWidth + $.fn.jerichoTab.tabPageWidth })
                    .animate({ left: 0 }, 0);
            }
        });
    },
    //make sure that the slider will be adjusted quickly to the tabpage after tab 'clicking' or tab 'initializing'
    adaptSlider: function() {
        return this.each(function() {
            if ($('.jericho_sliders').length > 0) {
                var offLeft = parseInt($.fn.jerichoTab.tabpage.css('left'));
                var curtag = '#', index = 0;
                for (var t in tabHash) {
                    if (tabHash[t].tabId == $(this).attr('id')) {
                        curtag += tabHash[t].tabId;
                        index = parseInt(t);
                        break;
                    }
                }
                //set the tabpage width
                var tabWidth = $.fn.jerichoTab.tabPageWidth - ($.fn.jerichoTab.slidersWidth * 2);
                //calculate the distance from the left side of tabpage
                var space_l = $.fn.jerichoTab.tabWidth * index + offLeft;
                //calculate the distance from the right side of tabpage
                var space_r = $.fn.jerichoTab.tabWidth * (index + 1) + offLeft;
                //window.console && console.log(space_l + '||' + space_r);
                function setSlider(pos, enable) {
                    $('.jericho_sliders[pos=' + pos + ']').attr({ 'slide': (enable ? 'yes' : 'no'), 'class': 'jericho_sliders jericho_slider' + pos + '_' + (enable ? 'enable' : 'disable') });
                }
                //slider to right to check whether it's a tab nearby left slider
                if ((space_l < 0 && space_l > -$.fn.jerichoTab.tabWidth) && (space_r > 0 && space_r < $.fn.jerichoTab.tabWidth)) {
                    //left
                    $.fn.jerichoTab.tabpage.animate({ left: -$.fn.jerichoTab.tabWidth * index }, 0, function() {
                        if (index == 0) setSlider('left', false);
                        else setSlider('left', true);
                        setSlider('right', true);
                    });
                }
                //slider to left to check whether it's a tab nearby right slider
                if ((space_l < tabWidth && space_l > tabWidth - $.fn.jerichoTab.tabWidth) && (space_r > tabWidth && space_r < tabWidth + $.fn.jerichoTab.tabWidth)) {
                    //right
                    $.fn.jerichoTab.tabpage.animate({ left: -$.fn.jerichoTab.tabWidth * (index + 1) + tabWidth }, 0, function() {
                        if (index == tabHash.length - 1) setSlider('right', false);
                        else setSlider('left', true);
                        setSlider('left', true);
                    });
                }
            }
        });
    },
    //apply event to the close anchor
    applyCloseEvent: function() {
        return this.each(function() {
            var me = this;
            $('.tab_close>a', this).click(function(e) {
                //prevents further propagation of the current event.
                e.stopPropagation();
                if ($(this).length == 0) return;
                //remove tab from tabpageholder
                $(me).animate({ 'opacity': '0', width: '0px' }, 100, function() {
                    //make the previous tab selected whether the removed tab was selected
                    var lastTab = $.fn.jerichoTab.tabpage.children('li').filter('.tab_selected');
                    if (lastTab.attr('id') == $(this).attr('id')) {
                        if($(this).prev().text() != ''){
                            $(this).prev().swapTabEnable().loadData();
                        }else{
                            $(this).next().swapTabEnable().loadData();
                        }
                    }
                    //clear the information of the removed tab from tabHash
                    for (var t in tabHash) {
                        if (tabHash[t].tabId == $(me).attr('id')) {
                            if (tabHash[t].tabFirer != null)
                                tabHash[t].tabFirer.removeAttr('jerichotabindex');
                            tabHash.splice(t, 1);
                        }
                    }
                    //adapt slider
                    $(me).applySlider().remove();
                    //remove contentholder
                    $('#jerichotabholder_' + $(me).attr('id').replace('jerichotab_', '')).remove();
                })
            });
            $(this).RightMenu('jerichotabmenu',{menuList:[
                {menuName:"刷新当前",clickEvent:"$('.tab_selected').loadData(true);"},
                {menuName:"关闭其它",clickEvent:"$('.tab_unselect .tab_close>a').click();"
                    +"setTimeout('$.fn.jerichoTab.resize();setTimeout(\\'$.fn.jerichoTab.resize();"
                    +"setTimeout(\\\\\'$.fn.jerichoTab.resize();\\\\\',1000);\\',500);',500);"}
            ]});
        });
    },
    //apply the "hover" effect and "onSelect" event
    applyHover: function() {
        return this.each(function() {
            $(this).hover(function() {
                if ($(this).hasClass('tab_unselect')) $(this).addClass('tab_unselect_h');
            }, function() {
                if ($(this).hasClass('tab_unselect_h')) $(this).removeClass('tab_unselect_h');
            }).mouseup(function() {
                if ($(this).hasClass('tab_selected')) return;
                //select this tab and hide the last selected tab
                var lastTab = $.fn.jerichoTab.tabpage.children('li').filter('.tab_selected');
                lastTab.attr('class', 'jericho_tabs tab_unselect');
                $('#jerichotabholder_' + lastTab.attr('id').replace('jerichotab_', '')).css({ 'display': 'none' });
                $(this).attr('class', 'jericho_tabs tab_selected').loadData().adaptSlider();
            });
        });
    },
    //switch the tab between the selected mode and the unselected mode, or v.v...
    swapTabEnable: function() {
        return this.each(function() {
            if ($(this).hasClass('tab_selected'))
                $(this).swapClass('tab_selected', 'tab_unselect');
            else if ($(this).hasClass('tab_unselect'))
                $(this).swapClass('tab_unselect', 'tab_selected');
        });
    },
    //change class from css1 to css2 of DOM
    swapClass: function(css1, css2) {
        return this.each(function() {
            $(this).removeClass(css1).addClass(css2);
        })
    },
    //if it takes a long time to load the data, show a loader to ui
    showLoader: function() {
        return this.each(function() {
            switch ($.fn.jerichoTab.loader) {
                case 'usebg':
                    //add a circular loading gif picture to the background of contentholder
                    $(this).addClass('loading');
                    break;
                case 'righttag':
                    //add a small loading gif picture and a banner to the right top corner of contentholder
                    if ($('#jerichotab_contentholder>.righttag').length == 0)
                        $('<div class="righttag">正在加载...</div>').appendTo($(this));
                    else
                        $('#jerichotab_contentholder>.righttag').css({ display: 'block' });
                    break;
            }
        });
    },
    //remove the loader
    removeLoader: function() {
        switch ($.fn.jerichoTab.loader) {
            case 'usebg':
                $('#jerichotab_contentholder').removeClass('loading');
                break;
            case 'righttag':
                $('#jerichotab_contentholder>.righttag').css({ display: 'none' });
                break;
        }
    }
});
//})(jQuery);

String.prototype.cut = function(len) {
    var position = 0;
    var result = [];
    var tale = '';
    for (var i = 0; i < this.length; i++) {
        if (position >= len) {
            tale = '...';
            break;
        }
        if (this.charCodeAt(i) > 255) {
            position += 2;
            result.push(this.substr(i, 1));
        }
        else {
            position++;
            result.push(this.substr(i, 1));
        }
    }
    return result.join("") + tale;
}

/*
 * 右键菜单,示例:$(this).RightMenu('myMenu2',{menuList:[{menuName:"菜单1",menuclass:"1",clickEvent:"divClick(1)"}]});
 */
$(function(){
    document.oncontextmenu=function(){return false;}//屏蔽右键
    document.onmousemove=mouseMove;//记录鼠标位置
});
var mx=0,my=0;
function mouseMove(ev){Ev=ev||window.event;var mousePos=mouseCoords(Ev);mx=mousePos.x;my=mousePos.y;}
function mouseCoords(ev){
    if(ev.pageX||ev.pageY){return{x:ev.pageX,y:ev.pageY};}
    return{x:ev.clientX,y:ev.clientY+$(document).scrollTop()};
}
$.fn.extend({RightMenu: function(id,options){
    options = $.extend({menuList:[]},options);
    var menuCount=options.menuList.length;
    if (!$("#"+id)[0]){
        var divMenuList="<div id=""+id+"" class="div_RightMenu"><div><ul class='ico'>";
        for(var i=0;i<menuCount;i++){
            divMenuList+="<li class=""+options.menuList[i].menuclass+"" onclick=""+options.menuList[i].clickEvent+"">"+options.menuList[i].menuName+"</li>";
        }
        divMenuList += "</ul></div><div>";
        $("body").append(divMenuList).find("#"+id).hide().find("li")
                .bind("mouseover",function(){$(this).addClass("RM_mouseover");})
                .bind("mouseout",function(){$(this).removeClass("RM_mouseover");});
        $(document).click(function(){$("#"+id).hide();});
    }
    return this.each(function(){
        this.oncontextmenu=function(){
            var mw=$('body').width(),mhh=$('html').height(),mbh=$('body').height(),
                w=$('#'+id).width(),h=$('#'+id).height(),
                mh=(mhh>mbh)?mhh:mbh;//最大高度 比较html与body的高度
            if(mh<h+my){my=mh-h;}//超 高
            if(mw<w+mx){mx=mw-w;}//超 宽
            $("#"+id).hide().css({top:my,left:mx}).show();
            $.fn.jerichoTab.resize(); // 修正弹出菜单时tab滚动被挤下去的问题
        }
    });
}});

Python:简单操作一下SQLite3

SQLite3

关于SQLite,下面引用:

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。[更多]

以下引用自网络:

SQLite3 可使用 sqlite3 模块与 Python 进行集成。sqlite3 模块是由 Gerhard Haring 编写的。它提供了一个与 PEP 249 描述的 DB-API 2.0 规范兼容的 SQL 接口。您不需要单独安装该模块,因为 Python 2.5.x 以上版本默认自带了该模块。
为了使用 sqlite3 模块,您首先必须创建一个表示数据库的连接对象,然后您可以有选择地创建光标对象,这将帮助您执行所有的 SQL 语句。[更多]

其实,上面这一堆,只是说明:Python 2.5+的版本,自带了SQLite.你可以直接使用!

python Logo
image-2438

简单工具

抽了一小会时间,简单写了个工具,只是简单封装了一下增删改查.在文件下面有示例,使用Python 3.5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
#! -*-coding=utf-8-*-

import sqlite3

'''


专注操作SQLite3.


-- SQLite3,方便.

@py-version 3.5
@version 2016.4.10
@author prd.

@version --> 0.1 初始.

'''
class SQLite3Tools(object):

    # 获取数据库
    def getDB(self):
        if not self.dbconn: # 如果还未赋值,则直接给一个
            self.dbconn = sqlite3.connect(self.dbFileName)
            return sqlite3.connect(self.dbFileName)
        else: # 已经赋值则直接返回.
            return self.dbconn
   
    # 关闭数据库连接.
    def closeDB(self):
        self.dbconn.close()
        self.dbconn = None

    # 工具入口函数getDB()
    def main(self,dbFileName):
        self.dbFileName = dbFileName
        self.dbconn = None

    # 执行:创建表
    def createTable(self,sql):
        self.getDB().execute(sql)
        self.closeDB()

    '''
    执行:插入数据

    @sql :可以为list类型(其中每个项均为str格式的sql语句)
          也可以为str类型.
    '''
    def insert(self,sql):
        if isinstance(sql,list):
            for xsqlitem in sql:
                self.getDB().execute(xsqlitem)
        else:
            self.getDB().execute(sql)
        self.getDB().commit()
        self.closeDB()

    # 执行:查询数据
    def select(self,sql):
        cursor = self.getDB().execute(sql)
        resultDict = cursor
        self.closeDB()
        return resultDict

    # 执行:更新或删除.
    def updateOrDelete(self,sql):
        print(self.getDB())
        self.getDB().execute(sql)
        print(self.getDB())
        self.getDB().commit()
        print(self.getDB())
        result = self.getDB().total_changes
        print(result)
        self.closeDB()
        return result

if __name__ == '__main__':
    print("仅用作演示,供参考.~")
    # 先获取实例
    # tools = SQLite3Tools()
   
    # 传入数据库文件路径.
    # tools.main("test.db")

    # 创建表.
    # tools.createTable('''
    # CREATE TABLE COMPANY
    #        (ID INT PRIMARY KEY     NOT NULL,
    #        NAME           TEXT    NOT NULL,
    #        AGE            INT     NOT NULL,
    #        ADDRESS        CHAR(50),
    #        SALARY         REAL);
    #       ''')
    # 创建表.END.

    # 单条插入.
    #sqllist = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00 )"
    #tools.insert(sqllist)
    # END.

    # 多条插入.
    # sqllist = ["INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (2, 'Allen', 25, 'Texas', 15000.00 )",\
    #   "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)    VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )",\
    #   "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)   VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )"]
    # tools.insert(sqllist)
    # END.

    # 查询
    # sqlselect = '''SELECT id, name, address, salary  from COMPANY'''
    # for x in tools.select(sqlselect):
    #   print(x)   
    # 查询END.

    # 更新
    # updatesql = "UPDATE COMPANY set NAME = 'wzretffgf' where ID=1 ;"
    # tools.updateOrDelete(updatesql)
    # 更新END.

    # 删除
    # updatesql = "DELETE FROM COMPANY  where ID=1 ;"
    # tools.updateOrDelete(updatesql)
    # 删除END.

    # 查询
    # sqlselect = '''SELECT id, name, address, salary  from COMPANY'''
    # for x in tools.select(sqlselect):
    #   print(x)   
    # 查询END.

Java8:利用Stream分组筛选数据

引起

有下面这一组数据,需要按关联字段、级别进行分组,第一时间想到的可能是在数据库使用SQL语句直接进行操作.但由于一些原因,无法在数据库中进行操作(这里仅用作示例,真实情况可能嵌套了好几层),鉴于Java 1.8发布很久很久了,就用Java 1.8的新特性实验了一下.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//因使用随机ID,因此部分数据可能出现不一致.
//ID[随便生成,仅用作示例] >>>>>>>> 名称 >>>>>> 关联的字段 >>>>>> 级别
9602177f-adb1-430a-a4a0-2287490bd9c2 >>>>>>> name38 >>>>>>> 550 >>>>>>> 1
13db2e97-0968-4d37-abcf-bd9afe88b1e4 >>>>>>> name39 >>>>>>> 1000 >>>>>>> 2
f1ed8688-a374-4d05-89a9-baaa6e8be546 >>>>>>> name64 >>>>>>> 550 >>>>>>> 1
c69c52b7-f327-436c-9bdc-6ffadb1f19a7 >>>>>>> name50 >>>>>>> 550 >>>>>>> 1
f0179d92-8fe5-4a46-95b0-c9f5671a9f70 >>>>>>> name79 >>>>>>> 1000 >>>>>>> 2
346e6f7f-7b1c-4c1c-b859-c197b55292f8 >>>>>>> name9 >>>>>>> 1000 >>>>>>> 2
ce3277ca-7b84-434f-8af0-0c7f06dc0ebb >>>>>>> name48 >>>>>>> 550 >>>>>>> 1
590bfddb-f9fd-4f4d-ab30-f71416b886ea >>>>>>> name75 >>>>>>> 1000 >>>>>>> 2
24884d2d-e403-456b-94b1-43fb11ec9e66 >>>>>>> name4 >>>>>>> 550 >>>>>>> 1
5dfb13ca-426e-4787-92b7-324ef58880b0 >>>>>>> name49 >>>>>>> 1000 >>>>>>> 2
ef44d0ee-0e44-4970-bdd2-87637a067260 >>>>>>> name40 >>>>>>> 550 >>>>>>> 1
cd815427-c410-4506-acf4-097871781955 >>>>>>> name4 >>>>>>> 550 >>>>>>> 1
785123b7-2584-47fc-92f8-8c850709b40b >>>>>>> name23 >>>>>>> 1000 >>>>>>> 2
e77b0f49-bd0d-4e31-80aa-29a0b9938a22 >>>>>>> name65 >>>>>>> 1000 >>>>>>> 2
64a81271-8020-453c-8b80-e7eb96e66fe6 >>>>>>> name52 >>>>>>> 550 >>>>>>> 1
921254ce-720a-4345-a10f-8382e6a361f5 >>>>>>> name9 >>>>>>> 1000 >>>>>>> 2
aecda534-d683-451e-9c7d-6927127d7d87 >>>>>>> name38 >>>>>>> 550 >>>>>>> 1
9309324f-c815-4b0c-9352-b3555f712235 >>>>>>> name29 >>>>>>> 1000 >>>>>>> 2
448736f6-0f76-4266-acdf-7b1faf2d8c24 >>>>>>> name14 >>>>>>> 550 >>>>>>> 1
039bdd87-5523-4be9-b0ac-ee305cf50a8c >>>>>>> name41 >>>>>>> 1000 >>>>>>> 2
065d2a1c-5c1b-45bb-9fce-d021c77addce >>>>>>> name71 >>>>>>> 1000 >>>>>>> 2
917c9e08-9cdd-45bf-803b-108f1b22de1a >>>>>>> name39 >>>>>>> 1000 >>>>>>> 2
caa7bacd-c08a-4ea7-a4ea-5ca844d82eab >>>>>>> name46 >>>>>>> 550 >>>>>>> 1
241f7f44-a387-4439-b44e-7d7d3e40528c >>>>>>> name8 >>>>>>> 550 >>>>>>> 1
f38befef-ffc4-4bad-88e9-46723db76371 >>>>>>> name10 >>>>>>> 550 >>>>>>> 1
72d4e95c-498d-4e4e-b0b3-3fc1b6b4ce40 >>>>>>> name54 >>>>>>> 550 >>>>>>> 1
bfb137e3-20e6-4b42-bb63-a0b7411f7e1b >>>>>>> name26 >>>>>>> 550 >>>>>>> 1
aa3c8aea-b387-44c6-8aaf-dc8d946510ff >>>>>>> name6 >>>>>>> 550 >>>>>>> 1
84a1cef4-dbac-44ce-a083-0650d5a074c1 >>>>>>> name0 >>>>>>> 550 >>>>>>> 1
8d1a87ad-daa7-4043-941e-1ab367ad063b >>>>>>> name18 >>>>>>> 550 >>>>>>> 1

java标志
image-2436

过程

首先定义了一个实体类[用来组织数据]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//Question.java

package com.company;

/**
 * Created by Administrator on 2016/4/6.
 */
public class Question {

    private String id ;// id
    private String name; // 名称
    private String parent;// 关联父级
    private String level; // 级别

    public Question() {
    }

    public Question(String id, String name, String parent, String level) {
        this.id = id;
        this.name = name;
        this.parent = parent;
        this.level = level;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getParent() {
        return parent;
    }

    public void setParent(String parent) {
        this.parent = parent;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }
}

实体定义好之后,在这里我使用了一个List来模拟从数据库中取出的数据,并且使用了随机数达到”随机”的假象.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//Main.java
package com.company;


import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author prd.
 * @version 2015.12.10
 */
public class Main {
    public static void main(String[] args) {
        //使用一个List模拟从数据库中取出来的数据
        List<Question> lists = new ArrayList<>();
        //往List中填充模拟数据
        for (int i = 0; i < 30; i++) {
            Question q = null;
            //控制填充的几率
            int random = (int) (Math.random() * 80);
            if (random % 2 == 0) {
                //使用UUID模拟ID属性
                q = new Question(String.valueOf(UUID.randomUUID()), "name" + random, "550", "1");
            } else {
                q = new Question(String.valueOf(UUID.randomUUID()), "name" + +random, "1000", "2");
            }
            lists.add(q);
        }

        //先输出List中的数据.
        //点击forEach可以查看相关注释:forEach是一种简化后的循环,同for类似.
        lists.forEach(x -> {
            System.out.println(x.getId() + " >>>>>>> " + x.getName() + " >>>>>>> " + x.getParent() + " >>>>>>> " +x.getLevel());
        });

        //筛选相关数据
        /*
             lists
                .stream() // 将List转换成一个"流",这是Java 1.8添加的新特性.关于更多Stream的知识,可参考:http://www.liaoxuefeng.com/article/001411309538536a1455df20d284b81a7bfa2f91db0f223000
                //通过java.util.stream.Stream接口的collect对List进行"收集操作",
                //也就是通过collect对List进行分组,
                //collect接收一个Collector接口的实现(通常使用Collectors,Collectors内部实现了Collector)
                .collect(Collectors.groupingBy(Question::getLevel, Collectors.groupingBy(Question::getParent)))
                //下面都是遍历过程,collect进行分组之后返回一个Map.第二个是我们需要的.
                .forEach((r, a) ->
                        a.forEach((x, y) ->
                                y.forEach(xy -> System.out.println(xy.getId() + ">>>>>>>>>" + xy.getName()))));
         */
        lists
                .stream()
                .collect(Collectors.groupingBy(Question::getLevel, Collectors.groupingBy(Question::getParent)))
                .forEach((r, a) ->
                        a.forEach((x, y) ->
                                y.forEach(xy -> System.out.println(xy.getId() + ">>>>>>>>>" + xy.getName()))));
        /*
                关于Stream可以参考:http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html 官方文档.
                Java 1.8新增很多类,变化比较大的就是:Lambda表达式,Stream API,新的java.util.Time时间库,default关键字等等.
                关于Java 1.8的变化可以参考:http://openjdk.java.net/projects/jdk8/milestones
         */
    }
}

输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//因使用随机ID,因此部分数据可能出现不一致.
cd2ac555-b9d8-40a2-9a1c-921a21335a96 >>>>>>> name4 >>>>>>> 550 >>>>>>> 1
1438b3e8-12c3-4dc7-875e-8317ef9b74db >>>>>>> name70 >>>>>>> 550 >>>>>>> 1
f5198af8-2f4d-46c3-815e-731ed81b6104 >>>>>>> name5 >>>>>>> 1000 >>>>>>> 2
16709764-24d2-43dc-954c-23b8537f2151 >>>>>>> name53 >>>>>>> 1000 >>>>>>> 2
4e70afba-4efc-436a-b0b9-88275da6edfe >>>>>>> name41 >>>>>>> 1000 >>>>>>> 2
09be4cbf-b28e-41e1-b91a-6445da4877ee >>>>>>> name0 >>>>>>> 550 >>>>>>> 1
955bc785-ef53-489d-bf5a-7b70046cd044 >>>>>>> name19 >>>>>>> 1000 >>>>>>> 2
50bed251-bdd4-49d0-9845-b8f00206c934 >>>>>>> name15 >>>>>>> 1000 >>>>>>> 2
5a5be641-57b7-43cd-bd20-c908377a2197 >>>>>>> name23 >>>>>>> 1000 >>>>>>> 2
cae3ab42-f576-4ca5-a9ea-2fd345be5c91 >>>>>>> name28 >>>>>>> 550 >>>>>>> 1
786448d6-48b7-468d-9e57-dc67c3980b2e >>>>>>> name76 >>>>>>> 550 >>>>>>> 1
40547eb8-6022-4259-a5fc-9ffa24052e9e >>>>>>> name4 >>>>>>> 550 >>>>>>> 1
a0880786-b59f-4b73-8c10-034803429287 >>>>>>> name64 >>>>>>> 550 >>>>>>> 1
16b058ff-a869-4ceb-8673-f31fb329823a >>>>>>> name27 >>>>>>> 1000 >>>>>>> 2
ea4c61d9-07d5-40e3-beb7-afa1693fb9cf >>>>>>> name18 >>>>>>> 550 >>>>>>> 1
f08e69df-3fa3-42ff-a152-f801c1c3e0b2 >>>>>>> name29 >>>>>>> 1000 >>>>>>> 2
0659902e-89ec-4a37-8c70-516fad0364fc >>>>>>> name45 >>>>>>> 1000 >>>>>>> 2
a51046c3-9ce8-4933-97de-6c27599c57cb >>>>>>> name27 >>>>>>> 1000 >>>>>>> 2
8865d74a-e4d4-4f68-849a-223ceb3bff3b >>>>>>> name59 >>>>>>> 1000 >>>>>>> 2
94b144bf-8d24-4602-b29a-2e7fc954bd85 >>>>>>> name21 >>>>>>> 1000 >>>>>>> 2
52fa654b-1447-40cf-93f3-d3904c85dcac >>>>>>> name75 >>>>>>> 1000 >>>>>>> 2
bbd114fa-0dcf-4957-ad97-56227886b61e >>>>>>> name7 >>>>>>> 1000 >>>>>>> 2
7b7e3017-1a85-4dca-bd86-fdfdc468fa31 >>>>>>> name67 >>>>>>> 1000 >>>>>>> 2
bcaf91ed-eaa0-4306-bb24-54c26511a3f7 >>>>>>> name44 >>>>>>> 550 >>>>>>> 1
181965c2-302d-45b5-9ee3-7ea7eb349f87 >>>>>>> name67 >>>>>>> 1000 >>>>>>> 2
eb600cbf-64e8-4f47-a3d7-cc8d06cd16e5 >>>>>>> name30 >>>>>>> 550 >>>>>>> 1
a78eed33-2adf-4078-88ef-4be494c217e4 >>>>>>> name1 >>>>>>> 1000 >>>>>>> 2
409e7d31-751c-4497-aa2b-702306d3bb5f >>>>>>> name4 >>>>>>> 550 >>>>>>> 1
964e7f5e-0a3c-4578-bcd1-be54744a899d >>>>>>> name53 >>>>>>> 1000 >>>>>>> 2
68d5027e-5b16-4ac2-9dc7-d01ed55dfb60 >>>>>>> name54 >>>>>>> 550 >>>>>>> 1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
cd2ac555-b9d8-40a2-9a1c-921a21335a96>>>>>>>>>name4>>>>>>>>>1>>>>>>>>>550
1438b3e8-12c3-4dc7-875e-8317ef9b74db>>>>>>>>>name70>>>>>>>>>1>>>>>>>>>550
09be4cbf-b28e-41e1-b91a-6445da4877ee>>>>>>>>>name0>>>>>>>>>1>>>>>>>>>550
cae3ab42-f576-4ca5-a9ea-2fd345be5c91>>>>>>>>>name28>>>>>>>>>1>>>>>>>>>550
786448d6-48b7-468d-9e57-dc67c3980b2e>>>>>>>>>name76>>>>>>>>>1>>>>>>>>>550
40547eb8-6022-4259-a5fc-9ffa24052e9e>>>>>>>>>name4>>>>>>>>>1>>>>>>>>>550
a0880786-b59f-4b73-8c10-034803429287>>>>>>>>>name64>>>>>>>>>1>>>>>>>>>550
ea4c61d9-07d5-40e3-beb7-afa1693fb9cf>>>>>>>>>name18>>>>>>>>>1>>>>>>>>>550
bcaf91ed-eaa0-4306-bb24-54c26511a3f7>>>>>>>>>name44>>>>>>>>>1>>>>>>>>>550
eb600cbf-64e8-4f47-a3d7-cc8d06cd16e5>>>>>>>>>name30>>>>>>>>>1>>>>>>>>>550
409e7d31-751c-4497-aa2b-702306d3bb5f>>>>>>>>>name4>>>>>>>>>1>>>>>>>>>550
68d5027e-5b16-4ac2-9dc7-d01ed55dfb60>>>>>>>>>name54>>>>>>>>>1>>>>>>>>>550
f5198af8-2f4d-46c3-815e-731ed81b6104>>>>>>>>>name5>>>>>>>>>2>>>>>>>>>1000
16709764-24d2-43dc-954c-23b8537f2151>>>>>>>>>name53>>>>>>>>>2>>>>>>>>>1000
4e70afba-4efc-436a-b0b9-88275da6edfe>>>>>>>>>name41>>>>>>>>>2>>>>>>>>>1000
955bc785-ef53-489d-bf5a-7b70046cd044>>>>>>>>>name19>>>>>>>>>2>>>>>>>>>1000
50bed251-bdd4-49d0-9845-b8f00206c934>>>>>>>>>name15>>>>>>>>>2>>>>>>>>>1000
5a5be641-57b7-43cd-bd20-c908377a2197>>>>>>>>>name23>>>>>>>>>2>>>>>>>>>1000
16b058ff-a869-4ceb-8673-f31fb329823a>>>>>>>>>name27>>>>>>>>>2>>>>>>>>>1000
f08e69df-3fa3-42ff-a152-f801c1c3e0b2>>>>>>>>>name29>>>>>>>>>2>>>>>>>>>1000
0659902e-89ec-4a37-8c70-516fad0364fc>>>>>>>>>name45>>>>>>>>>2>>>>>>>>>1000
a51046c3-9ce8-4933-97de-6c27599c57cb>>>>>>>>>name27>>>>>>>>>2>>>>>>>>>1000
8865d74a-e4d4-4f68-849a-223ceb3bff3b>>>>>>>>>name59>>>>>>>>>2>>>>>>>>>1000
94b144bf-8d24-4602-b29a-2e7fc954bd85>>>>>>>>>name21>>>>>>>>>2>>>>>>>>>1000
52fa654b-1447-40cf-93f3-d3904c85dcac>>>>>>>>>name75>>>>>>>>>2>>>>>>>>>1000
bbd114fa-0dcf-4957-ad97-56227886b61e>>>>>>>>>name7>>>>>>>>>2>>>>>>>>>1000
7b7e3017-1a85-4dca-bd86-fdfdc468fa31>>>>>>>>>name67>>>>>>>>>2>>>>>>>>>1000
181965c2-302d-45b5-9ee3-7ea7eb349f87>>>>>>>>>name67>>>>>>>>>2>>>>>>>>>1000
a78eed33-2adf-4078-88ef-4be494c217e4>>>>>>>>>name1>>>>>>>>>2>>>>>>>>>1000
964e7f5e-0a3c-4578-bcd1-be54744a899d>>>>>>>>>name53>>>>>>>>>2>>>>>>>>>1000