bindings
6 months ago
commands
1 week ago
pro
1 week ago
_acf-compatibility.js
1 year ago
_acf-condition-types.js
7 months ago
_acf-condition.js
1 year ago
_acf-conditions.js
1 year ago
_acf-field-accordion.js
6 months ago
_acf-field-button-group.js
7 months ago
_acf-field-checkbox.js
1 month ago
_acf-field-color-picker.js
7 months ago
_acf-field-date-picker.js
1 month ago
_acf-field-date-time-picker.js
1 month ago
_acf-field-file.js
1 month ago
_acf-field-google-map.js
6 months ago
_acf-field-icon-picker.js
1 month ago
_acf-field-image.js
1 month ago
_acf-field-link.js
1 year ago
_acf-field-oembed.js
1 month ago
_acf-field-page-link.js
1 year ago
_acf-field-post-object.js
1 year ago
_acf-field-radio.js
1 month ago
_acf-field-range.js
1 year ago
_acf-field-relationship.js
1 month ago
_acf-field-select.js
1 month ago
_acf-field-tab.js
3 weeks ago
_acf-field-taxonomy.js
7 months ago
_acf-field-time-picker.js
1 month ago
_acf-field-true-false.js
1 month ago
_acf-field-url.js
1 year ago
_acf-field-user.js
1 year ago
_acf-field-wysiwyg.js
1 month ago
_acf-field.js
1 year ago
_acf-fields.js
1 year ago
_acf-helpers.js
1 year ago
_acf-hooks.js
1 year ago
_acf-internal-post-type.js
7 months ago
_acf-media.js
1 week ago
_acf-modal.js
1 year ago
_acf-model.js
1 year ago
_acf-notice.js
7 months ago
_acf-panel.js
1 year ago
_acf-popup.js
7 months ago
_acf-postbox.js
1 year ago
_acf-screen.js
10 months ago
_acf-select2.js
1 year ago
_acf-tinymce.js
6 months ago
_acf-tooltip.js
10 months ago
_acf-unload.js
1 year ago
_acf-validation.js
1 month ago
_acf.js
7 months ago
_browse-fields-modal.js
7 months ago
_field-group-compatibility.js
1 year ago
_field-group-conditions.js
1 year ago
_field-group-field.js
3 months ago
_field-group-fields.js
10 months ago
_field-group-locations.js
1 year ago
_field-group-settings.js
1 year ago
_field-group.js
10 months ago
acf-escaped-html-notice.js
1 year ago
acf-field-group.js
1 year ago
acf-input.js
1 year ago
acf-internal-post-type.js
1 year ago
acf.js
1 year ago
_acf-tooltip.js
330 lines
| 1 | ( function ( $, undefined ) { |
| 2 | acf.newTooltip = function ( props ) { |
| 3 | // ensure object |
| 4 | if ( typeof props !== 'object' ) { |
| 5 | props = { text: props }; |
| 6 | } |
| 7 | |
| 8 | // confirmRemove |
| 9 | if ( props.confirmRemove !== undefined ) { |
| 10 | props.textConfirm = acf.__( 'Remove' ); |
| 11 | props.textCancel = acf.__( 'Cancel' ); |
| 12 | return new TooltipConfirm( props ); |
| 13 | |
| 14 | // confirm |
| 15 | } else if ( props.confirm !== undefined ) { |
| 16 | return new TooltipConfirm( props ); |
| 17 | |
| 18 | // default |
| 19 | } else { |
| 20 | return new Tooltip( props ); |
| 21 | } |
| 22 | }; |
| 23 | |
| 24 | var Tooltip = acf.Model.extend( { |
| 25 | data: { |
| 26 | text: '', |
| 27 | timeout: 0, |
| 28 | target: null, |
| 29 | }, |
| 30 | |
| 31 | tmpl: function () { |
| 32 | return '<div class="acf-tooltip"></div>'; |
| 33 | }, |
| 34 | |
| 35 | setup: function ( props ) { |
| 36 | $.extend( this.data, props ); |
| 37 | this.$el = $( this.tmpl() ); |
| 38 | }, |
| 39 | |
| 40 | initialize: function () { |
| 41 | // render |
| 42 | this.render(); |
| 43 | |
| 44 | // append |
| 45 | this.show(); |
| 46 | |
| 47 | // position |
| 48 | this.position(); |
| 49 | |
| 50 | // timeout |
| 51 | var timeout = this.get( 'timeout' ); |
| 52 | if ( timeout ) { |
| 53 | setTimeout( $.proxy( this.fade, this ), timeout ); |
| 54 | } |
| 55 | }, |
| 56 | |
| 57 | update: function ( props ) { |
| 58 | $.extend( this.data, props ); |
| 59 | this.initialize(); |
| 60 | }, |
| 61 | |
| 62 | render: function () { |
| 63 | this.$el.text( this.get( 'text' ) ); |
| 64 | }, |
| 65 | |
| 66 | show: function () { |
| 67 | $( 'body' ).append( this.$el ); |
| 68 | }, |
| 69 | |
| 70 | hide: function () { |
| 71 | this.$el.remove(); |
| 72 | }, |
| 73 | |
| 74 | fade: function () { |
| 75 | // add class |
| 76 | this.$el.addClass( 'acf-fade-up' ); |
| 77 | |
| 78 | // remove |
| 79 | this.setTimeout( function () { |
| 80 | this.remove(); |
| 81 | }, 250 ); |
| 82 | }, |
| 83 | |
| 84 | html: function ( html ) { |
| 85 | this.$el.html( html ); |
| 86 | }, |
| 87 | |
| 88 | position: function () { |
| 89 | // vars |
| 90 | var $tooltip = this.$el; |
| 91 | var $target = this.get( 'target' ); |
| 92 | if ( ! $target ) return; |
| 93 | |
| 94 | // Reset position. |
| 95 | $tooltip |
| 96 | .removeClass( 'right left bottom top' ) |
| 97 | .css( { top: 0, left: 0 } ); |
| 98 | |
| 99 | // Declare tolerance to edge of screen. |
| 100 | var tolerance = 10; |
| 101 | |
| 102 | // Find target position. |
| 103 | var targetWidth = $target.outerWidth(); |
| 104 | var targetHeight = $target.outerHeight(); |
| 105 | var targetTop = $target.offset().top; |
| 106 | var targetLeft = $target.offset().left; |
| 107 | |
| 108 | // Find tooltip position. |
| 109 | var tooltipWidth = $tooltip.outerWidth(); |
| 110 | var tooltipHeight = $tooltip.outerHeight(); |
| 111 | var tooltipTop = $tooltip.offset().top; // Should be 0, but WP media grid causes this to be 32 (toolbar padding). |
| 112 | |
| 113 | // Assume default top alignment. |
| 114 | var top = targetTop - tooltipHeight - tooltipTop; |
| 115 | var left = targetLeft + targetWidth / 2 - tooltipWidth / 2; |
| 116 | |
| 117 | // Check if too far left. |
| 118 | if ( left < tolerance ) { |
| 119 | $tooltip.addClass( 'right' ); |
| 120 | left = targetLeft + targetWidth; |
| 121 | top = |
| 122 | targetTop + |
| 123 | targetHeight / 2 - |
| 124 | tooltipHeight / 2 - |
| 125 | tooltipTop; |
| 126 | |
| 127 | // Check if too far right. |
| 128 | } else if ( |
| 129 | left + tooltipWidth + tolerance > |
| 130 | $( window ).width() |
| 131 | ) { |
| 132 | $tooltip.addClass( 'left' ); |
| 133 | left = targetLeft - tooltipWidth; |
| 134 | top = |
| 135 | targetTop + |
| 136 | targetHeight / 2 - |
| 137 | tooltipHeight / 2 - |
| 138 | tooltipTop; |
| 139 | |
| 140 | // Check if too far up. |
| 141 | } else if ( top - $( window ).scrollTop() < tolerance ) { |
| 142 | $tooltip.addClass( 'bottom' ); |
| 143 | top = targetTop + targetHeight - tooltipTop; |
| 144 | |
| 145 | // No collision with edges. |
| 146 | } else { |
| 147 | $tooltip.addClass( 'top' ); |
| 148 | } |
| 149 | |
| 150 | // update css |
| 151 | $tooltip.css( { top: top, left: left } ); |
| 152 | }, |
| 153 | } ); |
| 154 | |
| 155 | var TooltipConfirm = Tooltip.extend( { |
| 156 | data: { |
| 157 | text: '', |
| 158 | textConfirm: '', |
| 159 | textCancel: '', |
| 160 | target: null, |
| 161 | targetConfirm: true, |
| 162 | confirm: function () {}, |
| 163 | cancel: function () {}, |
| 164 | context: false, |
| 165 | }, |
| 166 | |
| 167 | events: { |
| 168 | 'click [data-event="cancel"]': 'onCancel', |
| 169 | 'click [data-event="confirm"]': 'onConfirm', |
| 170 | }, |
| 171 | |
| 172 | addEvents: function () { |
| 173 | // add events |
| 174 | acf.Model.prototype.addEvents.apply( this ); |
| 175 | |
| 176 | // vars |
| 177 | var $document = $( document ); |
| 178 | var $target = this.get( 'target' ); |
| 179 | |
| 180 | // add global 'cancel' click event |
| 181 | // - use timeout to avoid the current 'click' event triggering the onCancel function |
| 182 | this.setTimeout( function () { |
| 183 | this.on( $document, 'click', 'onCancel' ); |
| 184 | } ); |
| 185 | |
| 186 | // add target 'confirm' click event |
| 187 | // - allow setting to control this feature |
| 188 | if ( this.get( 'targetConfirm' ) ) { |
| 189 | this.on( $target, 'click', 'onConfirm' ); |
| 190 | } |
| 191 | }, |
| 192 | |
| 193 | removeEvents: function () { |
| 194 | // remove events |
| 195 | acf.Model.prototype.removeEvents.apply( this ); |
| 196 | |
| 197 | // vars |
| 198 | var $document = $( document ); |
| 199 | var $target = this.get( 'target' ); |
| 200 | |
| 201 | // remove custom events |
| 202 | this.off( $document, 'click' ); |
| 203 | this.off( $target, 'click' ); |
| 204 | }, |
| 205 | |
| 206 | render: function () { |
| 207 | // defaults |
| 208 | var text = this.get( 'text' ) || acf.__( 'Are you sure?' ); |
| 209 | var textConfirm = this.get( 'textConfirm' ) || acf.__( 'Yes' ); |
| 210 | var textCancel = this.get( 'textCancel' ) || acf.__( 'No' ); |
| 211 | |
| 212 | // html |
| 213 | var html = [ |
| 214 | text, |
| 215 | '<a href="#" data-event="confirm">' + textConfirm + '</a>', |
| 216 | '<a href="#" data-event="cancel">' + textCancel + '</a>', |
| 217 | ].join( ' ' ); |
| 218 | |
| 219 | // html |
| 220 | this.html( html ); |
| 221 | |
| 222 | // class |
| 223 | this.$el.addClass( '-confirm' ); |
| 224 | }, |
| 225 | |
| 226 | onCancel: function ( e, $el ) { |
| 227 | // prevent default |
| 228 | e.preventDefault(); |
| 229 | e.stopImmediatePropagation(); |
| 230 | |
| 231 | // callback |
| 232 | var callback = this.get( 'cancel' ); |
| 233 | var context = this.get( 'context' ) || this; |
| 234 | callback.apply( context, arguments ); |
| 235 | |
| 236 | //remove |
| 237 | this.remove(); |
| 238 | }, |
| 239 | |
| 240 | onConfirm: function ( e, $el ) { |
| 241 | // Prevent event from propagating completely to allow "targetConfirm" to be clicked. |
| 242 | e.preventDefault(); |
| 243 | e.stopImmediatePropagation(); |
| 244 | |
| 245 | // callback |
| 246 | var callback = this.get( 'confirm' ); |
| 247 | var context = this.get( 'context' ) || this; |
| 248 | callback.apply( context, arguments ); |
| 249 | |
| 250 | //remove |
| 251 | this.remove(); |
| 252 | }, |
| 253 | } ); |
| 254 | |
| 255 | // storage |
| 256 | acf.models.Tooltip = Tooltip; |
| 257 | acf.models.TooltipConfirm = TooltipConfirm; |
| 258 | |
| 259 | /** |
| 260 | * tooltipManager |
| 261 | * |
| 262 | * description |
| 263 | * |
| 264 | * @date 17/4/18 |
| 265 | * @since ACF 5.6.9 |
| 266 | * |
| 267 | * @param type $var Description. Default. |
| 268 | * @return type Description. |
| 269 | */ |
| 270 | |
| 271 | var tooltipHoverHelper = new acf.Model( { |
| 272 | tooltip: false, |
| 273 | |
| 274 | events: { |
| 275 | 'mouseenter .acf-js-tooltip': 'showTitle', |
| 276 | 'mouseup .acf-js-tooltip': 'hideTitle', |
| 277 | 'mouseleave .acf-js-tooltip': 'hideTitle', |
| 278 | 'focus .acf-js-tooltip': 'showTitle', |
| 279 | 'blur .acf-js-tooltip': 'hideTitle', |
| 280 | 'keyup .acf-js-tooltip': 'onKeyUp', |
| 281 | }, |
| 282 | |
| 283 | showTitle: function ( e, $el ) { |
| 284 | // vars |
| 285 | let title = $el.attr( 'title' ); |
| 286 | |
| 287 | // bail early if no title |
| 288 | if ( ! title ) { |
| 289 | return; |
| 290 | } |
| 291 | |
| 292 | // clear title to avoid default browser tooltip |
| 293 | $el.attr( 'title', '' ); |
| 294 | |
| 295 | $el.data( 'acf-js-tooltip-title', title ); |
| 296 | title = acf.strEscape( title ); |
| 297 | |
| 298 | // create |
| 299 | if ( ! this.tooltip ) { |
| 300 | this.tooltip = acf.newTooltip( { |
| 301 | text: title, |
| 302 | target: $el, |
| 303 | } ); |
| 304 | |
| 305 | // update |
| 306 | } else { |
| 307 | this.tooltip.update( { |
| 308 | text: title, |
| 309 | target: $el, |
| 310 | } ); |
| 311 | } |
| 312 | }, |
| 313 | |
| 314 | hideTitle: function ( e, $el ) { |
| 315 | // hide tooltip |
| 316 | this.tooltip.hide(); |
| 317 | $el.attr( 'title', $el.data( 'acf-js-tooltip-title' ) ); |
| 318 | |
| 319 | // restore title |
| 320 | $el.removeData( 'acf-js-tooltip-title' ); |
| 321 | }, |
| 322 | |
| 323 | onKeyUp: function ( e, $el ) { |
| 324 | if ( 'Escape' === e.key ) { |
| 325 | this.hideTitle( e, $el ); |
| 326 | } |
| 327 | }, |
| 328 | } ); |
| 329 | } )( jQuery ); |
| 330 |