Make WordPress Core

Changeset 24751


Ignore:
Timestamp:
07/19/2013 01:49:15 PM (12 years ago)
Author:
markjaquith
Message:

Revisions: Re-work how tick marks and tooltips are aligned. IE fixes.

  • Pixel-based alignment of tooltips.
  • Bottom-based alignment, so arrow lines up using CSS only.
  • Better RTL styles (mostly mirror-imaged).
  • Better RTL calculations in revisions.js (less logic).
  • Better IE support.

See #24736. Props markjaquith, adamsilverstein, ocean90.

Location:
trunk/wp-admin
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/css/colors-classic.css

    r24578 r24751  
    14871487
    14881488.revisions-tooltip,
    1489 .revisions-tooltip-arrow:after {
     1489.revisions-tooltip-arrow span {
    14901490    border-color: #d1e5ee;
    14911491    background-color: #fff;
  • trunk/wp-admin/css/colors-fresh.css

    r24658 r24751  
    13811381
    13821382.revisions-tooltip,
    1383 .revisions-tooltip-arrow:after {
     1383.revisions-tooltip-arrow span {
    13841384    border-color: #d7d7d7;
    13851385    background-color: #fff;
    1386 }
    1387 
    1388 
    1389 .revisions-tickmarks {
    1390     background-color: #f7f7f7;
    13911386}
    13921387
  • trunk/wp-admin/css/ie.css

    r24111 r24751  
    631631    height: 29px;
    632632}
     633
     634/* Revisions */
     635.revisions-tooltip-arrow span {
     636    left: 25px;
     637    top: -24px;
     638    filter: progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE7 */
     639}
     640
     641.revisions-controls .revisions-tickmarks > div {
     642    margin-right: -1px;
     643    border-width: 0 0 0 0;
     644        border-style: none;
     645}
  • trunk/wp-admin/css/wp-admin-rtl.css

    r24703 r24751  
    955955  11.2 - Post Revisions
    956956------------------------------------------------------------------------------*/
    957 .wp-slider .ui-slider-handle.left-handle:before,
    958 .wp-slider .ui-slider-handle.right-handle:before {
     957.wp-slider .ui-slider-handle.from-handle:before,
     958.wp-slider .ui-slider-handle.to-handle:before {
    959959    height: 8px;
    960960    width: 7px;
    961961}
    962962
    963 .wp-slider .ui-slider-handle.left-handle:before {
     963.wp-slider .ui-slider-handle.from-handle:before {
    964964    background-position: -5px -10px;
    965965    left: 6px;
    966966}
    967967
    968 .wp-slider .ui-slider-handle.right-handle:before {
     968.wp-slider .ui-slider-handle.to-handle:before {
    969969    background-position: -4px -29px;
    970970    left: 6px;
     
    10261026
    10271027.revisions-tooltip {
    1028     margin-right: -73px;
    1029     margin-left: 0;
     1028    margin-left: 0;
     1029    margin-right: -70px;
    10301030    -webkit-transition: right 15ms;
    10311031    -moz-transition:    right 15ms;
     
    10351035}
    10361036
     1037.ie8 .revisions-tooltip {
     1038    margin-right: -75px;
     1039}
     1040
    10371041.revisions-tooltip-arrow {
    10381042    right: 0;
     
    10411045}
    10421046
    1043 .revisions-tooltip-image {
     1047.revisions-tooltip-arrow > span {
     1048    right: 20px;
     1049}
     1050
     1051.revisions-tooltip img {
    10441052    float: right;
    10451053    margin: 2px 0 0 5px;
     1054}
     1055
     1056.revisions-tickmarks > div {
     1057    float: right;
     1058    border-width: 0 0 0 1px;
    10461059}
    10471060
  • trunk/wp-admin/css/wp-admin.css

    r24743 r24751  
    35123512  11.2 - Post Revisions
    35133513------------------------------------------------------------------------------*/
    3514 body.revision-php {
    3515     overflow-y: scroll; /* Force a scrollbar, so centering doesn't jump */
    3516 }
    3517 
    35183514.revisions-control-frame,
    35193515.revisions-diff-frame {
     
    35343530.revisions-tickmarks {
    35353531    position: relative;
    3536     margin: 0 auto 0;
     3532    margin: 0 auto;
    35373533    height: 0.8em;
    35383534    z-index: 2;
    35393535    top: 7px;
    3540     width: 70%;
     3536    width: 100%;
     3537    padding: 0 15%;
    35413538    -moz-box-sizing: border-box;
    35423539    -webkit-box-sizing: border-box;
    3543     -ms-box-sizing: border-box; /* ie8 only */
    35443540    box-sizing: border-box;
    35453541}
     
    35493545    height: 100%;
    35503546    float: left;
    3551     z-index: 10002;
     3547    z-index: 3;
    35523548    border-style: solid;
    3553     border-width: 0 0 0 1px;
     3549    border-width: 0 1px 0 0;
    35543550    -moz-box-sizing: border-box;
    35553551    -webkit-box-sizing: border-box;
    3556     -ms-box-sizing: border-box; /* ie8 only */
    35573552    box-sizing: border-box;
    35583553}
    35593554
    3560 .revisions-tickmarks > div:first-of-type {
    3561     border-left-width: 0;
     3555.revisions-tickmarks > div:last-child {
     3556    border-width: 0;
    35623557}
    35633558
     
    35893584    -o-transition:      opacity 0.5s;
    35903585    transition:         opacity 0.5s;
     3586    filter: alpha(opacity=0); /* ie8 and earlier */
    35913587}
    35923588
     
    35993595.revisions.loading .loading-indicator {
    36003596    opacity: 1;
     3597    filter: alpha(opacity=100); /* ie8 and earlier */
    36013598}
    36023599
     
    36113608.revisions.loading .diff {
    36123609    opacity: 0.5;
     3610    filter: alpha(opacity=50); /* ie8 and earlier */
    36133611}
    36143612
     
    36323630}
    36333631
     3632.revisions-previous,
     3633.revisions-next {
     3634    position: relative;
     3635    z-index: 4;
     3636}
     3637
    36343638.revisions-previous {
    36353639    float: left;
     
    36423646.wp-slider {
    36433647    width: 70%;
    3644     margin: 0 auto 0;
     3648    margin: 0 auto;
    36453649    top: -3px;
    36463650}
     
    37373741    position: absolute;
    37383742    bottom: 105px;
    3739     margin-left: -69px;
     3743    margin-right: 0;
     3744    margin-left: -70px;
    37403745    line-height: 28px;
    37413746    z-index: 9999;
     
    37743779}
    37753780
    3776 .revisions-tooltip-arrow:after {
     3781.revisions-tooltip-arrow > span {
    37773782    content: "";
    37783783    position: absolute;
     
    37883793}
    37893794
     3795.ie8 .revisions-tooltip-arrow > span {
     3796    left: 14px;
     3797    top: -25px;
     3798    -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */
     3799}
     3800
    37903801.revisions-tooltip,
    3791 .revisions-tooltip-arrow:after {
     3802.revisions-tooltip-arrow > span {
    37923803    border-width: 1px;
    37933804    border-style: solid;
     
    38293840}
    38303841
    3831 .wp-slider .ui-slider-handle.left-handle:before,
    3832 .wp-slider .ui-slider-handle.right-handle:before {
     3842.wp-slider .ui-slider-handle.from-handle:before,
     3843.wp-slider .ui-slider-handle.to-handle:before {
    38333844    height: 8px;
    38343845    width: 7px;
    38353846}
    38363847
    3837 .wp-slider .ui-slider-handle.left-handle:before {
     3848.wp-slider .ui-slider-handle.from-handle:before {
    38383849    background-position: -5px -84px;
    38393850    left: 7px;
    38403851}
    38413852
    3842 .wp-slider .ui-slider-handle.right-handle:before {
     3853.wp-slider .ui-slider-handle.to-handle:before {
    38433854    background-position: -4px -65px;
    38443855    left: 5px;
  • trunk/wp-admin/js/revisions.js

    r24732 r24751  
    1515        if ( window.console && revisions.debug )
    1616            console.log.apply( console, arguments );
     17    };
     18
     19    // Handy functions to help with positioning
     20    $.fn.allOffsets = function() {
     21        var offset = this.offset() || {top: 0, left: 0}, win = $(window);
     22        return _.extend( offset, {
     23            right:  win.width()  - offset.left - this.outerWidth(),
     24            bottom: win.height() - offset.top  - this.outerHeight()
     25        });
     26    };
     27
     28    $.fn.allPositions = function() {
     29        var position = this.position() || {top: 0, left: 0}, parent = this.parent();
     30        return _.extend( position, {
     31            right:  parent.outerWidth()  - position.left - this.outerWidth(),
     32            bottom: parent.outerHeight() - position.top  - this.outerHeight()
     33        });
    1734    };
    1835
     
    126143        defaults: {
    127144            revision: null,
     145            offset: {},
    128146            hovering: false, // Whether the mouse is hovering
    129147            scrubbing: false // Whether the mouse is scrubbing
     
    131149
    132150        initialize: function( options ) {
     151            this.frame = options.frame;
    133152            this.revisions = options.revisions;
    134153            this.slider = options.slider;
     
    137156            this.listenTo( this.slider, 'change:hovering', this.setHovering );
    138157            this.listenTo( this.slider, 'change:scrubbing', this.setScrubbing );
    139         },
     158
     159            this.set({ revision: this.frame.diff() });
     160        },
     161
    140162
    141163        updateRevision: function( revision ) {
     
    476498            wp.Backbone.View.prototype.render.apply( this, arguments );
    477499
     500            $('html').css( 'overflow-y', 'scroll' );
    478501            $('#wpbody-content .wrap').append( this.el );
    479502            this.updateCompareTwoMode();
     
    525548            });
    526549
     550            // Prep the tooltip model
     551            var tooltip = new revisions.model.Tooltip({
     552                frame: this.model,
     553                revisions: this.model.revisions,
     554                slider: slider
     555            });
     556
    527557            // Add the tooltip view
    528558            this.views.add( new revisions.view.Tooltip({
    529                 model: new revisions.model.Tooltip({
    530                     revisions: this.model.revisions,
    531                     slider: slider
    532                 })
     559                model: tooltip
    533560            }) );
    534561
    535562            // Add the tickmarks view
    536563            this.views.add( new revisions.view.Tickmarks({
    537                 model: this.model
     564                model: tooltip
    538565            }) );
    539566
     
    555582        className: 'revisions-tickmarks',
    556583
     584        initialize: function() {
     585            this.listenTo( this.model, 'change:revision', this.reportTickPosition );
     586        },
     587
     588        reportTickPosition: function( model, revision ) {
     589            var elWidth, offset, tick, index = this.model.revisions.indexOf( revision );
     590            if ( index === this.model.revisions.length - 1 ) {
     591                // Last one
     592                tick = this.$('div:nth-of-type(' + index + ')');
     593                offset = tick.allPositions();
     594                elWidth = tick.outerWidth();
     595                // adjust
     596                _.extend( offset, {
     597                    right: offset.right + elWidth + 1,
     598                    left: offset.left + elWidth + 1
     599                });
     600            } else {
     601                // Normal tick
     602                tick = this.$('div:nth-of-type(' + (index + 1) + ')');
     603                offset = tick.allPositions();
     604            }
     605            this.model.set({ offset: offset });
     606        },
     607
    557608        ready: function() {
    558609            var tickCount, tickWidth;
     
    561612
    562613            _(tickCount).times( function(){ this.$el.append( '<div></div>' ); }, this );
     614
    563615            this.$('div').css( 'width', ( 100 * tickWidth ) + '%' );
    564616        }
     
    626678        className: 'revisions-tooltip',
    627679        template: wp.template('revisions-tooltip'),
     680        direction: isRtl ? 'right' : 'left',
    628681
    629682        initialize: function( options ) {
    630             this.listenTo( this.model, 'change:revision', this.render );
     683            this.listenTo( this.model, 'change:offset', this.render );
    631684            this.listenTo( this.model, 'change:hovering', this.toggleVisibility );
    632685            this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility );
     686        },
     687
     688        prepare: function() {
     689            return this.model.get('revision').toJSON();
     690        },
     691
     692        render: function() {
     693            var css = {};
     694            wp.Backbone.View.prototype.render.apply( this, arguments );
     695            css[this.direction] = this.model.get('offset')[this.direction] + 'px';
     696            this.$el.css( css );
    633697        },
    634698
     
    643707                this.$el.stop().fadeTo( this.el.style.opacity * 300, 0, function(){ $(this).hide(); } );
    644708            return;
    645         },
    646 
    647         render: function() {
    648             var offset;
    649             // Check if a revision exists.
    650             if ( _.isNull( this.model.get('revision') ) )
    651                 return;
    652 
    653             this.$el.html( this.template( this.model.get('revision').toJSON() ) );
    654 
    655             // Set the position.
    656             offset = this.model.revisions.indexOf( this.model.get('revision') ) / ( this.model.revisions.length - 1 );
    657             // 15% to get us to the start of the slider
    658             // 0.7 to convert the slider-relative percentage to a page-relative percentage
    659             // 100 to convert to a percentage
    660             offset = 15 + (0.7 * offset * 100 ); // Now in a percentage
    661             this.$el.css( isRtl ? 'right' : 'left', offset + '%' );
    662709        }
    663710    });
     
    682729        },
    683730
    684         // Go to a specific modelindex, taking into account RTL mode.
     731        // Go to a specific model index
    685732        gotoModel: function( toIndex ) {
    686733            var attributes = {
    687                 to: this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for RTL.
     734                to: this.model.revisions.at( toIndex )
    688735            };
    689736            // If we're at the first revision, unset 'from'.
    690             if ( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for RTL
    691                 attributes.from = this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 2 : toIndex - 1 );
     737            if ( toIndex )
     738                attributes.from = this.model.revisions.at( toIndex - 1 );
    692739            else
    693740                this.model.unset('from', { silent: true });
     
    696743        },
    697744
    698         // Go to the 'next' revision, direction takes into account RTL mode.
     745        // Go to the 'next' revision
    699746        nextRevision: function() {
    700             var toIndex = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get('to') ) - 1 : this.model.revisions.indexOf( this.model.get('to') );
    701             toIndex     = isRtl ? toIndex - 1 : toIndex + 1;
     747            var toIndex = this.model.revisions.indexOf( this.model.get('to') ) + 1;
    702748            this.gotoModel( toIndex );
    703749        },
    704750
    705         // Go to the 'previous' revision, direction takes into account RTL mode.
     751        // Go to the 'previous' revision
    706752        previousRevision: function() {
    707             var toIndex = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get('to') ) - 1 : this.model.revisions.indexOf( this.model.get('to') );
    708             toIndex     = isRtl ? toIndex + 1 : toIndex - 1;
     753            var toIndex = this.model.revisions.indexOf( this.model.get('to') ) - 1;
    709754            this.gotoModel( toIndex );
    710755        },
     
    730775    revisions.view.Slider = wp.Backbone.View.extend({
    731776        className: 'wp-slider',
     777        direction: isRtl ? 'right' : 'left',
    732778
    733779        events: {
     
    758804        mouseMove: function( e ) {
    759805            var zoneCount = this.model.revisions.length - 1, // One fewer zone than models
    760                 sliderLeft = this.$el.offset().left, // Left edge of slider
     806                sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider
    761807                sliderWidth = this.$el.width(), // Width of slider
    762808                tickWidth = sliderWidth / zoneCount, // Calculated width of zone
    763                 actualX = e.clientX - sliderLeft, // Offset of mouse position in slider
    764                 currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 )  ) / tickWidth ); // Calculate the model index
    765 
    766             // Reverse direction in RTL mode.
    767             if ( isRtl )
    768                 currentModelIndex = this.model.revisions.length - currentModelIndex - 1;
     809                actualX = isRtl? $(window).width() - e.pageX : e.pageX; // Flipped for RTL - sliderFrom;
     810            actualX = actualX - sliderFrom; // Offset of mouse position in slider
     811            var currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 )  ) / tickWidth ); // Calculate the model index
    769812
    770813            // Ensure sane value for currentModelIndex.
     
    774817                currentModelIndex = this.model.revisions.length - 1;
    775818
    776             // Update the tooltip model
     819            // Update the tooltip mode
    777820            this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) });
    778821        },
     
    793836                // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    794837                handles.first()
    795                     .toggleClass( 'right-handle', !! isRtl )
    796                     .toggleClass( 'left-handle', ! isRtl );
     838                    .toggleClass( 'to-handle', !! isRtl )
     839                    .toggleClass( 'from-handle', ! isRtl );
    797840                handles.last()
    798                     .toggleClass( 'left-handle', !! isRtl )
    799                     .toggleClass( 'right-handle', ! isRtl );
     841                    .toggleClass( 'from-handle', !! isRtl )
     842                    .toggleClass( 'to-handle', ! isRtl );
    800843            } else {
    801                 handles.removeClass('left-handle right-handle');
    802             }
    803         },
    804 
    805         getSliderPosition: function( ui ){
    806             return isRtl ? this.model.revisions.length - ui.value - 1 : ui.value;
     844                handles.removeClass('from-handle to-handle');
     845            }
    807846        },
    808847
     
    813852            // overrides default jQuery UI step behavior.
    814853            $( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) {
    815                 var view            = e.data.view,
    816                     leftDragBoundary  = view.$el.offset().left, // Initial left boundary
    817                     sliderOffset      = leftDragBoundary,
    818                     sliderRightEdge   = leftDragBoundary + view.$el.width(),
    819                     rightDragBoundary = sliderRightEdge, // Initial right boundary
    820                     leftDragReset     = 0, // Initial left drag reset
    821                     rightDragReset    = sliderRightEdge - sliderOffset; // Initial right drag reset
     854                var view              = e.data.view,
     855                    leftDragBoundary  = view.$el.offset().left,
     856                    sliderOffset      = leftDragBoundary,
     857                    sliderRightEdge   = leftDragBoundary + view.$el.width(),
     858                    rightDragBoundary = sliderRightEdge,
     859                    leftDragReset     = '0',
     860                    rightDragReset    = '100%',
     861                    handle            = $( ui.handle );
    822862
    823863                // In two handle mode, ensure handles can't be dragged past each other.
    824864                // Adjust left/right boundaries and reset points.
    825865                if ( view.model.get('compareTwoMode') ) {
    826                     var rightHandle = $( ui.handle ).parent().find('.right-handle'),
    827                         leftHandle  = $( ui.handle ).parent().find('.left-handle');
    828 
    829                     if ( $( ui.handle ).hasClass('left-handle') ) {
    830                         // Dragging the left handle, boundary is right handle.
    831                         // RTL mode calculations reverse directions.
    832                         if ( isRtl ) {
    833                             leftDragBoundary = rightHandle.offset().left + rightHandle.width();
    834                             leftDragReset    = leftDragBoundary - sliderOffset;
    835                         } else {
    836                             rightDragBoundary = rightHandle.offset().left;
    837                             rightDragReset    = rightDragBoundary - sliderOffset;
    838                         }
    839                     } else {
    840                         // Dragging the right handle, boundary is the left handle.
    841                         // RTL mode calculations reverse directions.
    842                         if ( isRtl ) {
    843                             rightDragBoundary = leftHandle.offset().left;
    844                             rightDragReset    = rightDragBoundary - sliderOffset;
    845                         } else {
    846                             leftDragBoundary = leftHandle.offset().left + leftHandle.width() ;
    847                             leftDragReset    = leftDragBoundary - sliderOffset;
    848                         }
     866                    var handles = handle.parent().find('.ui-slider-handle');
     867                    if ( handle.is( handles.first() ) ) { // We're the left handle
     868                        rightDragBoundary = handles.last().offset().left;
     869                        rightDragReset    = rightDragBoundary - sliderOffset;
     870                    } else { // We're the right handle
     871                        leftDragBoundary = handles.first().offset().left + handles.first().width();
     872                        leftDragReset    = leftDragBoundary - sliderOffset;
    849873                    }
    850874                }
    851875
    852876                // Follow mouse movements, as long as handle remains inside slider.
    853                 if ( e.clientX < leftDragBoundary ) {
    854                     $( ui.handle ).css( 'left', leftDragReset ); // Mouse to left of slider.
    855                 } else if ( e.clientX > rightDragBoundary ) {
    856                     $( ui.handle ).css( 'left', rightDragReset ); // Mouse to right of slider.
     877                if ( e.pageX < leftDragBoundary ) {
     878                    handle.css( 'left', leftDragReset ); // Mouse to left of slider.
     879                } else if ( e.pageX > rightDragBoundary ) {
     880                    handle.css( 'left', rightDragReset ); // Mouse to right of slider.
    857881                } else {
    858                     $( ui.handle ).css( 'left', e.clientX - sliderOffset ); // Mouse in slider.
     882                    handle.css( 'left', e.pageX - sliderOffset ); // Mouse in slider.
    859883                }
    860884            } );
    861885        },
    862886
     887        getPosition: function( position ) {
     888            return isRtl ? this.model.revisions.length - position - 1: position;
     889        },
     890
    863891        // Responds to slide events
    864892        slide: function( event, ui ) {
    865             var attributes, movedRevision, sliderPosition;
     893            var attributes, movedRevision;
    866894            // Compare two revisions mode
    867895            if ( this.model.get('compareTwoMode') ) {
     
    869897                if ( ui.values[1] === ui.values[0] )
    870898                    return false;
    871 
     899                if ( isRtl )
     900                    ui.values.reverse();
    872901                attributes = {
    873                     to: this.model.revisions.at( isRtl ? this.model.revisions.length - ui.values[0] - 1 : ui.values[1] ),
    874                     from: this.model.revisions.at( isRtl ? this.model.revisions.length - ui.values[1] - 1 : ui.values[0] )
     902                    from: this.model.revisions.at( this.getPosition( ui.values[0] ) ),
     903                    to: this.model.revisions.at( this.getPosition( ui.values[1] ) )
    875904                };
    876                 if ( isRtl )
    877                     movedRevision = ui.value === ui.values[1] ? attributes.from : attributes.to;
    878                 else
    879                     movedRevision = ui.value === ui.values[0] ? attributes.from : attributes.to;
    880905            } else {
    881                 sliderPosition = this.getSliderPosition( ui );
    882906                attributes = {
    883                     to: this.model.revisions.at( sliderPosition )
     907                    to: this.model.revisions.at( this.getPosition( ui.value ) )
    884908                };
    885                 movedRevision = attributes.to;
    886909                // If we're at the first revision, unset 'from'.
    887                 if ( sliderPosition ) // Reverse directions for RTL.
    888                     attributes.from = this.model.revisions.at( sliderPosition - 1 );
     910                if ( this.getPosition( ui.value ) > 0 )
     911                    attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 );
    889912                else
    890913                    attributes.from = undefined;
    891914            }
     915            movedRevision = this.model.revisions.at( this.getPosition( ui.value ) );
    892916
    893917            // If we are scrubbing, a scrub to a revision is considered a hover
  • trunk/wp-admin/revision.php

    r24732 r24751  
    139139    <# } #>
    140140    </div>
    141     <div class="revisions-tooltip-arrow"></div>
     141    <div class="revisions-tooltip-arrow"><span></span></div>
    142142</script>
    143143
Note: See TracChangeset for help on using the changeset viewer.