Changeset 24658
- Timestamp:
- 07/11/2013 09:14:14 AM (10 years ago)
- Location:
- trunk/wp-admin
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-admin/css/colors-fresh.css
r24595 r24658 1392 1392 1393 1393 .revisions-tickmarks > div { 1394 b ackground-color: #ccc;1394 border-color: #aaa; 1395 1395 } 1396 1396 -
trunk/wp-admin/css/wp-admin.css
r24644 r24658 2550 2550 height: 0; 2551 2551 opacity: 0; 2552 -webkit-transition: height 1s, opacity 500ms;2553 transition: height 1s, opacity 500ms;2554 2552 } 2555 2553 … … 2557 2555 height: 22px; 2558 2556 opacity: 1; 2559 -webkit-transition: height 1s, opacity 500ms 500ms; 2560 transition: height 1s, opacity 500ms 500ms; 2557 } 2558 2559 tr.locked-info, tr.wp-locked .locked-info { 2560 -webkit-transition: height 1s, opacity 500ms; 2561 -moz-transition: height 1s, opacity 500ms; 2562 -ms-transition: height 1s, opacity 500ms; 2563 -o-transition: height 1s, opacity 500ms; 2564 transition: height 1s, opacity 500ms; 2561 2565 } 2562 2566 … … 3513 3517 z-index: 2; 3514 3518 top: 7px; 3519 width: 70%; 3520 box-sizing: border-box; 3515 3521 } 3516 3522 3517 3523 .revisions-tickmarks > div { 3518 height: 0.8em;3519 width: 1px;3520 float: left;3521 3524 position: relative; 3525 height: 100%; 3526 float: left; 3522 3527 z-index: 10002; 3528 border-style: solid; 3529 border-width: 0 0 0 1px; 3530 box-sizing: border-box; 3531 } 3532 3533 .revisions-tickmarks > div:first-of-type { 3534 border-left-width: 0; 3523 3535 } 3524 3536 … … 3653 3665 min-width: 130px; 3654 3666 padding: 4px; 3667 } 3668 3669 .revisions-tooltip.fade { 3670 -webkit-transition: opacity 200ms; 3671 -ms-transition: opacity 200ms; 3672 -moz-transition: opacity 200ms; 3673 -o-transition: opacity 200ms; 3674 transition: opacity 200ms; 3655 3675 } 3656 3676 -
trunk/wp-admin/js/revisions.js
r24652 r24658 32 32 min: 0, 33 33 max: 1, 34 step: 1 35 } 34 step: 1, 35 compareTwoMode: false 36 }, 37 38 initialize: function( options ) { 39 this.frame = options.frame; 40 this.revisions = options.revisions; 41 this.set({ 42 max: this.revisions.length - 1, 43 value: this.revisions.indexOf( this.revisions.get( revisions.settings.selectedRevision ) ), 44 compareTwoMode: this.frame.get('compareTwoMode') 45 }); 46 47 // Listen for changes to the revisions or mode from outside 48 this.listenTo( this.frame, 'update:revisions', this.receiveRevisions ); 49 this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode ); 50 51 // Listen for internal changes 52 this.listenTo( this, 'change:from', this.handleLocalChanges ); 53 this.listenTo( this, 'change:to', this.handleLocalChanges ); 54 55 // Listen for changes to the hovered revision 56 this.listenTo( this, 'change:hoveredRevision', this.hoverRevision ); 57 }, 58 59 // Called when a revision is hovered 60 hoverRevision: function( model, value ) { 61 this.trigger( 'hovered:revision', value ); 62 }, 63 64 // Called when `compareTwoMode` changes 65 updateMode: function( model, value ) { 66 this.set({ compareTwoMode: value }); 67 }, 68 69 // Called when `from` or `to` changes in the local model 70 handleLocalChanges: function() { 71 this.frame.set({ 72 from: this.get('from'), 73 to: this.get('to') 74 }); 75 }, 76 77 // Receives revisions changes from outside the model 78 receiveRevisions: function( from, to ) { 79 // Bail if nothing changed 80 if ( this.get('from') === from && this.get('to') === to ) 81 return; 82 83 this.set({ from: from, to: to }, { silent: true }); 84 this.trigger( 'update:revisions', from, to ); 85 } 86 36 87 }); 37 88 … … 39 90 defaults: { 40 91 revision: null, 41 position: 0 92 hovering: false, // Whether the mouse is hovering 93 scrubbing: false // Whether the mouse is scrubbing 94 }, 95 96 initialize: function( options ) { 97 this.revisions = options.revisions; 98 this.slider = options.slider; 99 100 this.listenTo( this.slider, 'hovered:revision', this.updateRevision ); 101 this.listenTo( this.slider, 'change:hovering', this.setHovering ); 102 this.listenTo( this.slider, 'change:scrubbing', this.setScrubbing ); 103 }, 104 105 updateRevision: function( revision ) { 106 this.set({ revision: revision }); 107 }, 108 109 setHovering: function( model, value ) { 110 this.set({ hovering: value }); 111 }, 112 113 setScrubbing: function( model, value ) { 114 this.set({ scrubbing: value }); 42 115 } 43 116 }); … … 47 120 revisions.model.Revisions = Backbone.Collection.extend({ 48 121 model: revisions.model.Revision, 122 123 initialize: function() { 124 _.bindAll( this, 'next', 'prev' ); 125 }, 49 126 50 127 comparator: function( a, b ) { … … 402 479 }) ); 403 480 481 // Prep the slider model 482 var slider = new revisions.model.Slider({ 483 frame: this.model, 484 revisions: this.model.revisions 485 }); 486 404 487 // Add the tooltip view 405 var tooltip = new revisions.view.Tooltip({ 406 model: new revisions.model.Tooltip() 407 }); 408 this.views.add( tooltip ); 409 410 // Add the Tickmarks view 488 this.views.add( new revisions.view.Tooltip({ 489 model: new revisions.model.Tooltip({ 490 revisions: this.model.revisions, 491 slider: slider 492 }) 493 }) ); 494 495 // Add the tickmarks view 411 496 this.views.add( new revisions.view.Tickmarks({ 412 497 model: this.model 413 498 }) ); 414 499 415 // Add the Slider view with a reference to the tooltipview500 // Add the slider view 416 501 this.views.add( new revisions.view.Slider({ 417 model: this.model, 418 tooltip: tooltip 502 model: slider 419 503 }) ); 420 504 … … 432 516 className: 'revisions-tickmarks', 433 517 434 numberOfTickmarksSet: function() { 435 var tickCount = this.model.revisions.length - 1, // One tickmark per model 436 sliderWidth = $('.wp-slider').parent().width() * 0.7, // Width of slider is 70% of container (reset on resize) 437 tickWidth = Math.floor( sliderWidth / tickCount ), // Divide width by # of tickmarks, round down 438 newSiderWidth = ( ( tickWidth + 1 ) * tickCount ) + 1, // Calculate the actual width 439 tickNumber; 440 441 $('.wp-slider').css( 'width', newSiderWidth ); // Reset the slider width to match the calculated tick size 442 this.$el.css( 'width', newSiderWidth ); // Match the tickmark div width 443 444 for ( tickNumber = 0; tickNumber <= tickCount; tickNumber++ ){ 445 this.$el.append('<div style="left:' + ( tickWidth * tickNumber ) + 'px;"></div>'); 446 } 518 render: function() { 519 var tickCount, tickWidth; 520 521 tickCount = this.model.revisions.length - 1; 522 tickWidth = 1 / tickCount; 523 524 this.$el.html(''); 525 _(tickCount).times( function(){ this.$el.append( '<div></div>' ); }, this ); 526 527 this.$('div').css( 'width', ( 100 * tickWidth ) + '%' ); 447 528 }, 448 529 449 530 ready: function() { 450 var self = this; 451 self.numberOfTickmarksSet(); 452 $( window ).on( 'resize', _.debounce( function() { 453 self.$el.html(''); 454 self.numberOfTickmarksSet(); 455 }, 50 ) ); 531 this.render(); 456 532 } 457 533 }); … … 528 604 template: wp.template('revisions-tooltip'), 529 605 530 initialize: function() { 531 this.listenTo( this.model, 'change', this.render ); 606 initialize: function( options ) { 607 this.listenTo( this.model, 'change:revision', this.render ); 608 this.listenTo( this.model, 'change:hovering', this.toggleVisibility ); 609 this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility ); 532 610 }, 533 611 534 612 ready: function() { 535 // Hide tooltip on start. 536 this.$el.addClass('hidden'); 537 }, 538 539 show: function() { 540 this.$el.removeClass('hidden'); 541 }, 542 543 hide: function() { 544 this.$el.addClass('hidden'); 613 this.toggleVisibility({ immediate: true }); 614 }, 615 616 visible: function() { 617 return this.model.get( 'scrubbing' ) || this.model.get( 'hovering' ); 618 }, 619 620 toggleVisibility: function( options ) { 621 options = options || {}; 622 var visible = this.visible() 623 if ( visible ) { // Immediate show 624 // this.$el.removeClass('fade'); 625 this.$el.css( 'opacity', 1 ); 626 } else if ( options.immediate ) { // Immediate fade out 627 this.$el.addClass('fade'); 628 this.$el.css( 'opacity', 0 ); 629 } else { // Wait a bit, make sure we're really done, then fade it out 630 _.delay( function( view ) { 631 if ( ! view.visible() ) 632 view.toggleVisibility({ immediate: true }); 633 }, 500, this ); 634 } 545 635 }, 546 636 547 637 render: function() { 638 var offset; 548 639 // Check if a revision exists. 549 if ( null === this.model.get('revision') )640 if ( _.isNull( this.model.get('revision') ) ) 550 641 return; 551 642 … … 554 645 555 646 // Set the position. 556 var offset = $('.revisions-buttons').offset().left; 557 this.$el.css( 'left', this.model.get('position') - offset ); 647 offset = this.model.revisions.indexOf( this.model.get('revision') ) / ( this.model.revisions.length - 1 ); 648 // 15% to get us to the start of the slider 649 // 0.7 to convert the slider-relative percentage to a page-relative percentage 650 // 100 to convert to a percentage 651 offset = 15 + (0.7 * offset * 100 ); // Now in a percentage 652 this.$el.css( 'left', offset + '%' ); 558 653 } 559 654 }); … … 627 722 628 723 // The slider view. 629 // Encapsulates all of the configuration for the jQuery UI slider into a view.630 724 revisions.view.Slider = wp.Backbone.View.extend({ 631 725 className: 'wp-slider', 632 726 633 727 events: { 634 'mousemove' : 'mousemove', 635 'mouseleave' : 'mouseleave', 636 'mouseenter' : 'mouseenter' 637 }, 638 639 initialize: function( options ) { 640 _.bindAll( this, 'start', 'slide', 'stop' ); 641 642 this.tooltip = options.tooltip; 643 644 // Create the slider model from the provided collection data. 645 var latestRevisionIndex = this.model.revisions.length - 1; 646 647 // Find the initially selected revision 648 var initiallySelectedRevisionIndex = 649 this.model.revisions.indexOf( 650 this.model.revisions.findWhere({ id: revisions.settings.selectedRevision }) ); 651 652 this.settings = new revisions.model.Slider({ 653 max: latestRevisionIndex, 654 value: initiallySelectedRevisionIndex, 728 'mousemove' : 'mouseMove', 729 'mouseleave' : 'mouseLeave', 730 'mouseenter' : 'mouseEnter' 731 }, 732 733 initialize: function() { 734 _.bindAll( this, 'start', 'slide', 'stop', 'mouseMove' ); 735 this.listenTo( this.model, 'change:compareTwoMode', this.updateSliderSettings ); 736 this.listenTo( this.model, 'update:revisions', this.updateSliderSettings ); 737 }, 738 739 ready: function() { 740 this.$el.slider( _.extend( this.model.toJSON(), { 655 741 start: this.start, 656 742 slide: this.slide, 657 743 stop: this.stop 658 }); 659 }, 660 661 ready: function() { 662 // Refresh the currently selected revision position in case router has set it. 663 this.settings.attributes.value = this.model.revisions.indexOf( 664 this.model.revisions.findWhere({ id: revisions.settings.selectedRevision }) ); 665 666 // And update the slider in case the route has set it. 667 this.updateSliderSettings(); 668 this.slide( '', this.settings.attributes ); 669 this.$el.slider( this.settings.toJSON() ); 670 671 // Listen for changes in Compare Two Mode setting 672 this.listenTo( this.model, 'change:compareTwoMode', this.updateSliderSettings ); 673 674 this.settings.on( 'change', function() { 675 this.updateSliderSettings(); 676 }, this ); 677 678 // Listen for changes to the revisions 679 this.listenTo( this.model, 'update:revisions', this.updateRevisions ); 680 }, 681 682 mousemove: function( e ) { 683 var tickCount = this.model.revisions.length - 1, // One tickmark per model 684 sliderLeft = Math.ceil( this.$el.offset().left ), // Left edge of slider 744 }) ); 745 746 this.listenTo( this, 'slide:stop', this.updateSliderSettings ); 747 }, 748 749 mouseMove: function( e ) { 750 var zoneCount = this.model.revisions.length - 1, // One fewer zone than models 751 sliderLeft = this.$el.offset().left, // Left edge of slider 685 752 sliderWidth = this.$el.width(), // Width of slider 686 tickWidth = Math.floor( sliderWidth / tickCount ), // Calculated width of tickmark753 tickWidth = sliderWidth / zoneCount, // Calculated width of zone 687 754 actualX = e.clientX - sliderLeft, // Offset of mouse position in slider 688 currentModelIndex = Math.floor( ( actualX + tickWidth / 2 ) / tickWidth ), // Calculate the model index 689 tooltipPosition = sliderLeft + 2 + currentModelIndex * tickWidth; // Stick tooltip to tickmark 755 currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 ) ) / tickWidth ); // Calculate the model index 690 756 691 757 // Reverse direction in RTL mode. … … 700 766 701 767 // Update the tooltip model 702 this.tooltip.model.set( 'revision', this.model.revisions.at( currentModelIndex ) ); 703 this.tooltip.model.set( 'position', tooltipPosition ); 704 }, 705 706 mouseleave: function( e ) { 707 this.tooltip.hide(); 708 }, 709 710 mouseenter: function( e ) { 711 this.tooltip.show(); 768 this.model.set({ 769 'hoveredRevision': this.model.revisions.at( currentModelIndex ) 770 }); 771 }, 772 773 mouseLeave: function() { 774 this.model.set({ hovering: false }); 775 }, 776 777 mouseEnter: function() { 778 this.model.set({ hovering: true }); 712 779 }, 713 780 714 781 updateSliderSettings: function() { 715 var handles ;782 var handles, leftValue, rightValue; 716 783 717 784 if ( this.model.get('compareTwoMode') ) { 718 var leftValue, rightValue; 719 720 // In single handle mode, the 1st stored revision is 'blank' and the 'from' model is not set 721 // In this case we move the to index over one 722 if ( _.isUndefined( this.model.get('from') ) ) { 723 if ( isRtl ) { 724 leftValue = this.model.revisions.length - this.model.revisions.indexOf( this.model.get('to') ) - 2; 725 rightValue = leftValue + 1; 726 } else { 727 leftValue = this.model.revisions.indexOf( this.model.get('to') ); 728 rightValue = leftValue + 1; 729 } 730 } else { 731 leftValue = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get('to') ) - 1 : 785 leftValue = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get('to') ) - 1 : 732 786 this.model.revisions.indexOf( this.model.get('from') ), 733 787 rightValue = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get('from') ) - 1 : 734 788 this.model.revisions.indexOf( this.model.get('to') ); 735 }736 789 737 790 // Set handles to current from / to models. … … 767 820 }, 768 821 769 updateRevisions: function( from, to ) {770 // Update the view settings when the revisions have changed.771 if ( this.model.get('compareTwoMode') ) {772 this.settings.set({ 'values': [773 this.model.revisions.indexOf( from ),774 this.model.revisions.indexOf( to )775 ] });776 } else {777 this.settings.set({ 'value': this.model.revisions.indexOf( to ) });778 }779 },780 781 822 getSliderPosition: function( ui ){ 782 823 return isRtl ? this.model.revisions.length - ui.value - 1 : ui.value; … … 784 825 785 826 start: function( event, ui ) { 827 this.model.set({ scrubbing: true }); 828 786 829 // Track the mouse position to enable smooth dragging, 787 830 // overrides default jQuery UI step behavior. 788 $( window ).on( 'mousemove ', { view: this }, function( e ) {789 var view 831 $( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) { 832 var view = e.data.view, 790 833 leftDragBoundary = view.$el.offset().left, // Initial left boundary 791 834 sliderOffset = leftDragBoundary, … … 797 840 // In two handle mode, ensure handles can't be dragged past each other. 798 841 // Adjust left/right boundaries and reset points. 799 if ( view.model. get('compareTwoMode') ) {842 if ( view.model.frame.get('compareTwoMode') ) { 800 843 var rightHandle = $( ui.handle ).parent().find('.right-handle'), 801 844 leftHandle = $( ui.handle ).parent().find('.left-handle'); … … 835 878 }, 836 879 880 // Responds to slide events 837 881 slide: function( event, ui ) { 838 882 var attributes; 839 883 // Compare two revisions mode 840 if ( ! _.isUndefined( ui.values ) && this.model. get('compareTwoMode') ) {884 if ( ! _.isUndefined( ui.values ) && this.model.frame.get('compareTwoMode') ) { 841 885 // Prevent sliders from occupying same spot 842 886 if ( ui.values[1] === ui.values[0] ) … … 859 903 attributes.from = this.model.revisions.at( sliderPosition - 1 ); 860 904 else 861 this.model.unset( 'from', { silent: true });905 attributes.from = undefined; 862 906 } 863 907 this.model.set( attributes ); 908 909 // If we are scrubbing, a scrub to a revision is considered a hover 910 if ( this.model.get( 'scrubbing' ) ) { 911 this.model.set({ 912 'hoveredRevision': attributes.to 913 }); 914 } 864 915 }, 865 916 866 917 stop: function( event, ui ) { 867 $( window ).off('mousemove'); 868 869 // Reset settings props handle back to the step position. 870 this.settings.trigger('change'); 918 $( window ).off('mousemove.wp.revisions'); 919 this.updateSliderSettings(); 920 this.model.set({ scrubbing: false }); 871 921 } 872 922 }); … … 913 963 // If `b` is undefined, this is an 'at/:to' route, for a single revision 914 964 if ( _.isUndefined( b ) ) { 915 b = a; 916 a = 0; 965 b = this.model.revisions.get( a ); 966 a = this.model.revisions.prev( b ); 967 b = b ? b.id : 0; 968 a = a ? a.id : 0 917 969 compareTwo = false; 918 970 } else { … … 926 978 927 979 if ( ! _.isUndefined( this.model ) ) { 928 var selectedToRevision = this.model.revisions. findWhere({ id: to }),929 selectedFromRevision = this.model.revisions. findWhere({ id: from });980 var selectedToRevision = this.model.revisions.get( to ), 981 selectedFromRevision = this.model.revisions.get( from ); 930 982 931 983 this.model.set({
Note: See TracChangeset
for help on using the changeset viewer.