230500
This commit is contained in:
@@ -0,0 +1,464 @@
|
||||
/**
|
||||
* @output wp-includes/js/admin-bar.js
|
||||
*/
|
||||
/**
|
||||
* Admin bar with Vanilla JS, no external dependencies.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {Object} document The document object.
|
||||
* @param {Object} window The window object.
|
||||
* @param {Object} navigator The navigator object.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
( function( document, window, navigator ) {
|
||||
document.addEventListener( 'DOMContentLoaded', function() {
|
||||
var adminBar = document.getElementById( 'wpadminbar' ),
|
||||
topMenuItems,
|
||||
allMenuItems,
|
||||
adminBarLogout,
|
||||
adminBarSearchForm,
|
||||
shortlink,
|
||||
skipLink,
|
||||
mobileEvent,
|
||||
adminBarSearchInput,
|
||||
i;
|
||||
|
||||
if ( ! adminBar || ! ( 'querySelectorAll' in adminBar ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
topMenuItems = adminBar.querySelectorAll( 'li.menupop' );
|
||||
allMenuItems = adminBar.querySelectorAll( '.ab-item' );
|
||||
adminBarLogout = document.querySelector( '#wp-admin-bar-logout a' );
|
||||
adminBarSearchForm = document.getElementById( 'adminbarsearch' );
|
||||
shortlink = document.getElementById( 'wp-admin-bar-get-shortlink' );
|
||||
skipLink = adminBar.querySelector( '.screen-reader-shortcut' );
|
||||
mobileEvent = /Mobile\/.+Safari/.test( navigator.userAgent ) ? 'touchstart' : 'click';
|
||||
|
||||
// Remove nojs class after the DOM is loaded.
|
||||
removeClass( adminBar, 'nojs' );
|
||||
|
||||
if ( 'ontouchstart' in window ) {
|
||||
// Remove hover class when the user touches outside the menu items.
|
||||
document.body.addEventListener( mobileEvent, function( e ) {
|
||||
if ( ! getClosest( e.target, 'li.menupop' ) ) {
|
||||
removeAllHoverClass( topMenuItems );
|
||||
}
|
||||
} );
|
||||
|
||||
// Add listener for menu items to toggle hover class by touches.
|
||||
// Remove the callback later for better performance.
|
||||
adminBar.addEventListener( 'touchstart', function bindMobileEvents() {
|
||||
for ( var i = 0; i < topMenuItems.length; i++ ) {
|
||||
topMenuItems[i].addEventListener( 'click', mobileHover.bind( null, topMenuItems ) );
|
||||
}
|
||||
|
||||
adminBar.removeEventListener( 'touchstart', bindMobileEvents );
|
||||
} );
|
||||
}
|
||||
|
||||
// Scroll page to top when clicking on the admin bar.
|
||||
adminBar.addEventListener( 'click', scrollToTop );
|
||||
|
||||
for ( i = 0; i < topMenuItems.length; i++ ) {
|
||||
// Adds or removes the hover class based on the hover intent.
|
||||
window.hoverintent(
|
||||
topMenuItems[i],
|
||||
addClass.bind( null, topMenuItems[i], 'hover' ),
|
||||
removeClass.bind( null, topMenuItems[i], 'hover' )
|
||||
).options( {
|
||||
timeout: 180
|
||||
} );
|
||||
|
||||
// Toggle hover class if the enter key is pressed.
|
||||
topMenuItems[i].addEventListener( 'keydown', toggleHoverIfEnter );
|
||||
}
|
||||
|
||||
// Remove hover class if the escape key is pressed.
|
||||
for ( i = 0; i < allMenuItems.length; i++ ) {
|
||||
allMenuItems[i].addEventListener( 'keydown', removeHoverIfEscape );
|
||||
}
|
||||
|
||||
if ( adminBarSearchForm ) {
|
||||
adminBarSearchInput = document.getElementById( 'adminbar-search' );
|
||||
|
||||
// Adds the adminbar-focused class on focus.
|
||||
adminBarSearchInput.addEventListener( 'focus', function() {
|
||||
addClass( adminBarSearchForm, 'adminbar-focused' );
|
||||
} );
|
||||
|
||||
// Removes the adminbar-focused class on blur.
|
||||
adminBarSearchInput.addEventListener( 'blur', function() {
|
||||
removeClass( adminBarSearchForm, 'adminbar-focused' );
|
||||
} );
|
||||
}
|
||||
|
||||
if ( skipLink ) {
|
||||
// Focus the target of skip link after pressing Enter.
|
||||
skipLink.addEventListener( 'keydown', focusTargetAfterEnter );
|
||||
}
|
||||
|
||||
if ( shortlink ) {
|
||||
shortlink.addEventListener( 'click', clickShortlink );
|
||||
}
|
||||
|
||||
// Prevents the toolbar from covering up content when a hash is present in the URL.
|
||||
if ( window.location.hash ) {
|
||||
window.scrollBy( 0, -32 );
|
||||
}
|
||||
|
||||
// Clear sessionStorage on logging out.
|
||||
if ( adminBarLogout ) {
|
||||
adminBarLogout.addEventListener( 'click', emptySessionStorage );
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Remove hover class for top level menu item when escape is pressed.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {Event} event The keydown event.
|
||||
*/
|
||||
function removeHoverIfEscape( event ) {
|
||||
var wrapper;
|
||||
|
||||
if ( event.which !== 27 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper = getClosest( event.target, '.menupop' );
|
||||
|
||||
if ( ! wrapper ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.querySelector( '.menupop > .ab-item' ).focus();
|
||||
removeClass( wrapper, 'hover' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle hover class for top level menu item when enter is pressed.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {Event} event The keydown event.
|
||||
*/
|
||||
function toggleHoverIfEnter( event ) {
|
||||
var wrapper;
|
||||
|
||||
// Follow link if pressing Ctrl and/or Shift with Enter (opening in a new tab or window).
|
||||
if ( event.which !== 13 || event.ctrlKey || event.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper = getClosest( event.target, '.menupop' );
|
||||
|
||||
if ( ! wrapper ) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if ( hasClass( wrapper, 'hover' ) ) {
|
||||
removeClass( wrapper, 'hover' );
|
||||
} else {
|
||||
addClass( wrapper, 'hover' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the target of skip link after pressing Enter.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {Event} event The keydown event.
|
||||
*/
|
||||
function focusTargetAfterEnter( event ) {
|
||||
var id, userAgent;
|
||||
|
||||
if ( event.which !== 13 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
id = event.target.getAttribute( 'href' );
|
||||
userAgent = navigator.userAgent.toLowerCase();
|
||||
|
||||
if ( userAgent.indexOf( 'applewebkit' ) > -1 && id && id.charAt( 0 ) === '#' ) {
|
||||
setTimeout( function() {
|
||||
var target = document.getElementById( id.replace( '#', '' ) );
|
||||
|
||||
if ( target ) {
|
||||
target.setAttribute( 'tabIndex', '0' );
|
||||
target.focus();
|
||||
}
|
||||
}, 100 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toogle hover class for mobile devices.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {NodeList} topMenuItems All menu items.
|
||||
* @param {Event} event The click event.
|
||||
*/
|
||||
function mobileHover( topMenuItems, event ) {
|
||||
var wrapper;
|
||||
|
||||
if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
wrapper = getClosest( event.target, '.menupop' );
|
||||
|
||||
if ( ! wrapper ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( hasClass( wrapper, 'hover' ) ) {
|
||||
removeClass( wrapper, 'hover' );
|
||||
} else {
|
||||
removeAllHoverClass( topMenuItems );
|
||||
addClass( wrapper, 'hover' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the click on the Shortlink link in the adminbar.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @since 5.3.1 Use querySelector to clean up the function.
|
||||
*
|
||||
* @param {Event} event The click event.
|
||||
* @return {boolean} Returns false to prevent default click behavior.
|
||||
*/
|
||||
function clickShortlink( event ) {
|
||||
var wrapper = event.target.parentNode,
|
||||
input;
|
||||
|
||||
if ( wrapper ) {
|
||||
input = wrapper.querySelector( '.shortlink-input' );
|
||||
}
|
||||
|
||||
if ( ! input ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// (Old) IE doesn't support preventDefault, and does support returnValue.
|
||||
if ( event.preventDefault ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
event.returnValue = false;
|
||||
|
||||
addClass( wrapper, 'selected' );
|
||||
|
||||
input.focus();
|
||||
input.select();
|
||||
input.onblur = function() {
|
||||
removeClass( wrapper, 'selected' );
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear sessionStorage on logging out.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*/
|
||||
function emptySessionStorage() {
|
||||
if ( 'sessionStorage' in window ) {
|
||||
try {
|
||||
for ( var key in sessionStorage ) {
|
||||
if ( key.indexOf( 'wp-autosave-' ) > -1 ) {
|
||||
sessionStorage.removeItem( key );
|
||||
}
|
||||
}
|
||||
} catch ( er ) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if element has class.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {HTMLElement} element The HTML element.
|
||||
* @param {string} className The class name.
|
||||
* @return {boolean} Whether the element has the className.
|
||||
*/
|
||||
function hasClass( element, className ) {
|
||||
var classNames;
|
||||
|
||||
if ( ! element ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( element.classList && element.classList.contains ) {
|
||||
return element.classList.contains( className );
|
||||
} else if ( element.className ) {
|
||||
classNames = element.className.split( ' ' );
|
||||
return classNames.indexOf( className ) > -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add class to an element.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {HTMLElement} element The HTML element.
|
||||
* @param {string} className The class name.
|
||||
*/
|
||||
function addClass( element, className ) {
|
||||
if ( ! element ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( element.classList && element.classList.add ) {
|
||||
element.classList.add( className );
|
||||
} else if ( ! hasClass( element, className ) ) {
|
||||
if ( element.className ) {
|
||||
element.className += ' ';
|
||||
}
|
||||
|
||||
element.className += className;
|
||||
}
|
||||
|
||||
var menuItemToggle = element.querySelector( 'a' );
|
||||
if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
|
||||
menuItemToggle.setAttribute( 'aria-expanded', 'true' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove class from an element.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {HTMLElement} element The HTML element.
|
||||
* @param {string} className The class name.
|
||||
*/
|
||||
function removeClass( element, className ) {
|
||||
var testName,
|
||||
classes;
|
||||
|
||||
if ( ! element || ! hasClass( element, className ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( element.classList && element.classList.remove ) {
|
||||
element.classList.remove( className );
|
||||
} else {
|
||||
testName = ' ' + className + ' ';
|
||||
classes = ' ' + element.className + ' ';
|
||||
|
||||
while ( classes.indexOf( testName ) > -1 ) {
|
||||
classes = classes.replace( testName, '' );
|
||||
}
|
||||
|
||||
element.className = classes.replace( /^[\s]+|[\s]+$/g, '' );
|
||||
}
|
||||
|
||||
var menuItemToggle = element.querySelector( 'a' );
|
||||
if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
|
||||
menuItemToggle.setAttribute( 'aria-expanded', 'false' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove hover class for all menu items.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {NodeList} topMenuItems All menu items.
|
||||
*/
|
||||
function removeAllHoverClass( topMenuItems ) {
|
||||
if ( topMenuItems && topMenuItems.length ) {
|
||||
for ( var i = 0; i < topMenuItems.length; i++ ) {
|
||||
removeClass( topMenuItems[i], 'hover' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls to the top of the page.
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param {Event} event The Click event.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function scrollToTop( event ) {
|
||||
// Only scroll when clicking on the wpadminbar, not on menus or submenus.
|
||||
if (
|
||||
event.target &&
|
||||
event.target.id !== 'wpadminbar' &&
|
||||
event.target.id !== 'wp-admin-bar-top-secondary'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
window.scrollTo( {
|
||||
top: -32,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
} );
|
||||
} catch ( er ) {
|
||||
window.scrollTo( 0, -32 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get closest Element.
|
||||
*
|
||||
* @since 5.3.1
|
||||
*
|
||||
* @param {HTMLElement} el Element to get parent.
|
||||
* @param {string} selector CSS selector to match.
|
||||
*/
|
||||
function getClosest( el, selector ) {
|
||||
if ( ! window.Element.prototype.matches ) {
|
||||
// Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/Element/matches.
|
||||
window.Element.prototype.matches =
|
||||
window.Element.prototype.matchesSelector ||
|
||||
window.Element.prototype.mozMatchesSelector ||
|
||||
window.Element.prototype.msMatchesSelector ||
|
||||
window.Element.prototype.oMatchesSelector ||
|
||||
window.Element.prototype.webkitMatchesSelector ||
|
||||
function( s ) {
|
||||
var matches = ( this.document || this.ownerDocument ).querySelectorAll( s ),
|
||||
i = matches.length;
|
||||
|
||||
while ( --i >= 0 && matches.item( i ) !== this ) { }
|
||||
|
||||
return i > -1;
|
||||
};
|
||||
}
|
||||
|
||||
// Get the closest matching elent.
|
||||
for ( ; el && el !== document; el = el.parentNode ) {
|
||||
if ( el.matches( selector ) ) {
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
} )( document, window, navigator );
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(l,u,d){function f(e){27===e.which&&(e=w(e.target,".menupop"))&&(e.querySelector(".menupop > .ab-item").focus(),y(e,"hover"))}function p(e){var t;13!==e.which||e.ctrlKey||e.shiftKey||w(e.target,".ab-sub-wrapper")||(t=w(e.target,".menupop"))&&(e.preventDefault(),(a(t,"hover")?y:g)(t,"hover"))}function h(e){var t;13===e.which&&(t=e.target.getAttribute("href"),-1<d.userAgent.toLowerCase().indexOf("applewebkit"))&&t&&"#"===t.charAt(0)&&setTimeout(function(){var e=l.getElementById(t.replace("#",""));e&&(e.setAttribute("tabIndex","0"),e.focus())},100)}function m(e,t){!w(t.target,".ab-sub-wrapper")&&(t.preventDefault(),t=w(t.target,".menupop"))&&(a(t,"hover")?y:(E(e),g))(t,"hover")}function v(e){var t,r=e.target.parentNode;if(t=r?r.querySelector(".shortlink-input"):t)return e.preventDefault&&e.preventDefault(),e.returnValue=!1,g(r,"selected"),t.focus(),t.select(),!(t.onblur=function(){y(r,"selected")})}function b(){if("sessionStorage"in u)try{for(var e in sessionStorage)-1<e.indexOf("wp-autosave-")&&sessionStorage.removeItem(e)}catch(e){}}function a(e,t){return e&&(e.classList&&e.classList.contains?e.classList.contains(t):e.className&&-1<e.className.split(" ").indexOf(t))}function g(e,t){e&&(e.classList&&e.classList.add?e.classList.add(t):a(e,t)||(e.className&&(e.className+=" "),e.className+=t),e=e.querySelector("a"),"hover"===t)&&e&&e.hasAttribute("aria-expanded")&&e.setAttribute("aria-expanded","true")}function y(e,t){var r,n;if(e&&a(e,t)){if(e.classList&&e.classList.remove)e.classList.remove(t);else{for(r=" "+t+" ",n=" "+e.className+" ";-1<n.indexOf(r);)n=n.replace(r,"");e.className=n.replace(/^[\s]+|[\s]+$/g,"")}e=e.querySelector("a");"hover"===t&&e&&e.hasAttribute("aria-expanded")&&e.setAttribute("aria-expanded","false")}}function E(e){if(e&&e.length)for(var t=0;t<e.length;t++)y(e[t],"hover")}function L(e){if(!e.target||"wpadminbar"===e.target.id||"wp-admin-bar-top-secondary"===e.target.id)try{u.scrollTo({top:-32,left:0,behavior:"smooth"})}catch(e){u.scrollTo(0,-32)}}function w(e,t){for(u.Element.prototype.matches||(u.Element.prototype.matches=u.Element.prototype.matchesSelector||u.Element.prototype.mozMatchesSelector||u.Element.prototype.msMatchesSelector||u.Element.prototype.oMatchesSelector||u.Element.prototype.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),r=t.length;0<=--r&&t.item(r)!==this;);return-1<r});e&&e!==l;e=e.parentNode)if(e.matches(t))return e;return null}l.addEventListener("DOMContentLoaded",function(){var r,e,t,n,a,o,s,i,c=l.getElementById("wpadminbar");if(c&&"querySelectorAll"in c){r=c.querySelectorAll("li.menupop"),e=c.querySelectorAll(".ab-item"),t=l.querySelector("#wp-admin-bar-logout a"),n=l.getElementById("adminbarsearch"),a=l.getElementById("wp-admin-bar-get-shortlink"),o=c.querySelector(".screen-reader-shortcut"),s=/Mobile\/.+Safari/.test(d.userAgent)?"touchstart":"click",y(c,"nojs"),"ontouchstart"in u&&(l.body.addEventListener(s,function(e){w(e.target,"li.menupop")||E(r)}),c.addEventListener("touchstart",function e(){for(var t=0;t<r.length;t++)r[t].addEventListener("click",m.bind(null,r));c.removeEventListener("touchstart",e)})),c.addEventListener("click",L);for(i=0;i<r.length;i++)u.hoverintent(r[i],g.bind(null,r[i],"hover"),y.bind(null,r[i],"hover")).options({timeout:180}),r[i].addEventListener("keydown",p);for(i=0;i<e.length;i++)e[i].addEventListener("keydown",f);n&&((s=l.getElementById("adminbar-search")).addEventListener("focus",function(){g(n,"adminbar-focused")}),s.addEventListener("blur",function(){y(n,"adminbar-focused")})),o&&o.addEventListener("keydown",h),a&&a.addEventListener("click",v),u.location.hash&&u.scrollBy(0,-32),t&&t.addEventListener("click",b)}})}(document,window,navigator);
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Thin jQuery.ajax wrapper for WP REST API requests.
|
||||
*
|
||||
* Currently only applies to requests that do not use the `wp-api.js` Backbone
|
||||
* client library, though this may change. Serves several purposes:
|
||||
*
|
||||
* - Allows overriding these requests as needed by customized WP installations.
|
||||
* - Sends the REST API nonce as a request header.
|
||||
* - Allows specifying only an endpoint namespace/path instead of a full URL.
|
||||
*
|
||||
* @since 4.9.0
|
||||
* @since 5.6.0 Added overriding of the "PUT" and "DELETE" methods with "POST".
|
||||
* Added an "application/json" Accept header to all requests.
|
||||
* @output wp-includes/js/api-request.js
|
||||
*/
|
||||
|
||||
( function( $ ) {
|
||||
var wpApiSettings = window.wpApiSettings;
|
||||
|
||||
function apiRequest( options ) {
|
||||
options = apiRequest.buildAjaxOptions( options );
|
||||
return apiRequest.transport( options );
|
||||
}
|
||||
|
||||
apiRequest.buildAjaxOptions = function( options ) {
|
||||
var url = options.url;
|
||||
var path = options.path;
|
||||
var method = options.method;
|
||||
var namespaceTrimmed, endpointTrimmed, apiRoot;
|
||||
var headers, addNonceHeader, addAcceptHeader, headerName;
|
||||
|
||||
if (
|
||||
typeof options.namespace === 'string' &&
|
||||
typeof options.endpoint === 'string'
|
||||
) {
|
||||
namespaceTrimmed = options.namespace.replace( /^\/|\/$/g, '' );
|
||||
endpointTrimmed = options.endpoint.replace( /^\//, '' );
|
||||
if ( endpointTrimmed ) {
|
||||
path = namespaceTrimmed + '/' + endpointTrimmed;
|
||||
} else {
|
||||
path = namespaceTrimmed;
|
||||
}
|
||||
}
|
||||
if ( typeof path === 'string' ) {
|
||||
apiRoot = wpApiSettings.root;
|
||||
path = path.replace( /^\//, '' );
|
||||
|
||||
// API root may already include query parameter prefix
|
||||
// if site is configured to use plain permalinks.
|
||||
if ( 'string' === typeof apiRoot && -1 !== apiRoot.indexOf( '?' ) ) {
|
||||
path = path.replace( '?', '&' );
|
||||
}
|
||||
|
||||
url = apiRoot + path;
|
||||
}
|
||||
|
||||
// If ?_wpnonce=... is present, no need to add a nonce header.
|
||||
addNonceHeader = ! ( options.data && options.data._wpnonce );
|
||||
addAcceptHeader = true;
|
||||
|
||||
headers = options.headers || {};
|
||||
|
||||
for ( headerName in headers ) {
|
||||
if ( ! headers.hasOwnProperty( headerName ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an 'X-WP-Nonce' or 'Accept' header (or any case-insensitive variation
|
||||
// thereof) was specified, no need to add the header again.
|
||||
switch ( headerName.toLowerCase() ) {
|
||||
case 'x-wp-nonce':
|
||||
addNonceHeader = false;
|
||||
break;
|
||||
case 'accept':
|
||||
addAcceptHeader = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( addNonceHeader ) {
|
||||
// Do not mutate the original headers object, if any.
|
||||
headers = $.extend( {
|
||||
'X-WP-Nonce': wpApiSettings.nonce
|
||||
}, headers );
|
||||
}
|
||||
|
||||
if ( addAcceptHeader ) {
|
||||
headers = $.extend( {
|
||||
'Accept': 'application/json, */*;q=0.1'
|
||||
}, headers );
|
||||
}
|
||||
|
||||
if ( typeof method === 'string' ) {
|
||||
method = method.toUpperCase();
|
||||
|
||||
if ( 'PUT' === method || 'DELETE' === method ) {
|
||||
headers = $.extend( {
|
||||
'X-HTTP-Method-Override': method
|
||||
}, headers );
|
||||
|
||||
method = 'POST';
|
||||
}
|
||||
}
|
||||
|
||||
// Do not mutate the original options object.
|
||||
options = $.extend( {}, options, {
|
||||
headers: headers,
|
||||
url: url,
|
||||
method: method
|
||||
} );
|
||||
|
||||
delete options.path;
|
||||
delete options.namespace;
|
||||
delete options.endpoint;
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
apiRequest.transport = $.ajax;
|
||||
|
||||
/** @namespace wp */
|
||||
window.wp = window.wp || {};
|
||||
window.wp.apiRequest = apiRequest;
|
||||
} )( jQuery );
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(c){var w=window.wpApiSettings;function t(e){return e=t.buildAjaxOptions(e),t.transport(e)}t.buildAjaxOptions=function(e){var t,n,a,p,o,r,i=e.url,d=e.path,s=e.method;for(r in"string"==typeof e.namespace&&"string"==typeof e.endpoint&&(t=e.namespace.replace(/^\/|\/$/g,""),d=(n=e.endpoint.replace(/^\//,""))?t+"/"+n:t),"string"==typeof d&&(n=w.root,d=d.replace(/^\//,""),"string"==typeof n&&-1!==n.indexOf("?")&&(d=d.replace("?","&")),i=n+d),p=!(e.data&&e.data._wpnonce),o=!0,a=e.headers||{})if(a.hasOwnProperty(r))switch(r.toLowerCase()){case"x-wp-nonce":p=!1;break;case"accept":o=!1}return p&&(a=c.extend({"X-WP-Nonce":w.nonce},a)),o&&(a=c.extend({Accept:"application/json, */*;q=0.1"},a)),"string"!=typeof s||"PUT"!==(s=s.toUpperCase())&&"DELETE"!==s||(a=c.extend({"X-HTTP-Method-Override":s},a),s="POST"),delete(e=c.extend({},e,{headers:a,url:i,method:s})).path,delete e.namespace,delete e.endpoint,e},t.transport=c.ajax,window.wp=window.wp||{},window.wp.apiRequest=t}(jQuery);
|
||||
@@ -0,0 +1,903 @@
|
||||
/**
|
||||
* @output wp-includes/js/autosave.js
|
||||
*/
|
||||
|
||||
/* global tinymce, wpCookies, autosaveL10n, switchEditors */
|
||||
// Back-compat.
|
||||
window.autosave = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds autosave to the window object on dom ready.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {jQuery} $ jQuery object.
|
||||
* @param {window} The window object.
|
||||
*
|
||||
*/
|
||||
( function( $, window ) {
|
||||
/**
|
||||
* Auto saves the post.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {Object}
|
||||
* {{
|
||||
* getPostData: getPostData,
|
||||
* getCompareString: getCompareString,
|
||||
* disableButtons: disableButtons,
|
||||
* enableButtons: enableButtons,
|
||||
* local: ({hasStorage, getSavedPostData, save, suspend, resume}|*),
|
||||
* server: ({tempBlockSave, triggerSave, postChanged, suspend, resume}|*)
|
||||
* }}
|
||||
* The object with all functions for autosave.
|
||||
*/
|
||||
function autosave() {
|
||||
var initialCompareString,
|
||||
initialCompareData = {},
|
||||
lastTriggerSave = 0,
|
||||
$document = $( document );
|
||||
|
||||
/**
|
||||
* Sets the initial compare data.
|
||||
*
|
||||
* @since 5.6.1
|
||||
*/
|
||||
function setInitialCompare() {
|
||||
initialCompareData = {
|
||||
post_title: $( '#title' ).val() || '',
|
||||
content: $( '#content' ).val() || '',
|
||||
excerpt: $( '#excerpt' ).val() || ''
|
||||
};
|
||||
|
||||
initialCompareString = getCompareString( initialCompareData );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data saved in both local and remote autosave.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {string} type The type of autosave either local or remote.
|
||||
*
|
||||
* @return {Object} Object containing the post data.
|
||||
*/
|
||||
function getPostData( type ) {
|
||||
var post_name, parent_id, data,
|
||||
time = ( new Date() ).getTime(),
|
||||
cats = [],
|
||||
editor = getEditor();
|
||||
|
||||
// Don't run editor.save() more often than every 3 seconds.
|
||||
// It is resource intensive and might slow down typing in long posts on slow devices.
|
||||
if ( editor && editor.isDirty() && ! editor.isHidden() && time - 3000 > lastTriggerSave ) {
|
||||
editor.save();
|
||||
lastTriggerSave = time;
|
||||
}
|
||||
|
||||
data = {
|
||||
post_id: $( '#post_ID' ).val() || 0,
|
||||
post_type: $( '#post_type' ).val() || '',
|
||||
post_author: $( '#post_author' ).val() || '',
|
||||
post_title: $( '#title' ).val() || '',
|
||||
content: $( '#content' ).val() || '',
|
||||
excerpt: $( '#excerpt' ).val() || ''
|
||||
};
|
||||
|
||||
if ( type === 'local' ) {
|
||||
return data;
|
||||
}
|
||||
|
||||
$( 'input[id^="in-category-"]:checked' ).each( function() {
|
||||
cats.push( this.value );
|
||||
});
|
||||
data.catslist = cats.join(',');
|
||||
|
||||
if ( post_name = $( '#post_name' ).val() ) {
|
||||
data.post_name = post_name;
|
||||
}
|
||||
|
||||
if ( parent_id = $( '#parent_id' ).val() ) {
|
||||
data.parent_id = parent_id;
|
||||
}
|
||||
|
||||
if ( $( '#comment_status' ).prop( 'checked' ) ) {
|
||||
data.comment_status = 'open';
|
||||
}
|
||||
|
||||
if ( $( '#ping_status' ).prop( 'checked' ) ) {
|
||||
data.ping_status = 'open';
|
||||
}
|
||||
|
||||
if ( $( '#auto_draft' ).val() === '1' ) {
|
||||
data.auto_draft = '1';
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the title, content and excerpt. This is used to track changes
|
||||
* when auto-saving.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {Object} postData The object containing the post data.
|
||||
*
|
||||
* @return {string} A concatenated string with title, content and excerpt.
|
||||
*/
|
||||
function getCompareString( postData ) {
|
||||
if ( typeof postData === 'object' ) {
|
||||
return ( postData.post_title || '' ) + '::' + ( postData.content || '' ) + '::' + ( postData.excerpt || '' );
|
||||
}
|
||||
|
||||
return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables save buttons.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function disableButtons() {
|
||||
$document.trigger('autosave-disable-buttons');
|
||||
|
||||
// Re-enable 5 sec later. Just gives autosave a head start to avoid collisions.
|
||||
setTimeout( enableButtons, 5000 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables save buttons.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function enableButtons() {
|
||||
$document.trigger( 'autosave-enable-buttons' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content editor.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return {boolean|*} Returns either false if the editor is undefined,
|
||||
* or the instance of the content editor.
|
||||
*/
|
||||
function getEditor() {
|
||||
return typeof tinymce !== 'undefined' && tinymce.get('content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Autosave in localStorage.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {
|
||||
* {
|
||||
* hasStorage: *,
|
||||
* getSavedPostData: getSavedPostData,
|
||||
* save: save,
|
||||
* suspend: suspend,
|
||||
* resume: resume
|
||||
* }
|
||||
* }
|
||||
* The object with all functions for local storage autosave.
|
||||
*/
|
||||
function autosaveLocal() {
|
||||
var blog_id, post_id, hasStorage, intervalTimer,
|
||||
lastCompareString,
|
||||
isSuspended = false;
|
||||
|
||||
/**
|
||||
* Checks if the browser supports sessionStorage and it's not disabled.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {boolean} True if the sessionStorage is supported and enabled.
|
||||
*/
|
||||
function checkStorage() {
|
||||
var test = Math.random().toString(),
|
||||
result = false;
|
||||
|
||||
try {
|
||||
window.sessionStorage.setItem( 'wp-test', test );
|
||||
result = window.sessionStorage.getItem( 'wp-test' ) === test;
|
||||
window.sessionStorage.removeItem( 'wp-test' );
|
||||
} catch(e) {}
|
||||
|
||||
hasStorage = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the local storage.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {boolean|Object} False if no sessionStorage in the browser or an Object
|
||||
* containing all postData for this blog.
|
||||
*/
|
||||
function getStorage() {
|
||||
var stored_obj = false;
|
||||
// Separate local storage containers for each blog_id.
|
||||
if ( hasStorage && blog_id ) {
|
||||
stored_obj = sessionStorage.getItem( 'wp-autosave-' + blog_id );
|
||||
|
||||
if ( stored_obj ) {
|
||||
stored_obj = JSON.parse( stored_obj );
|
||||
} else {
|
||||
stored_obj = {};
|
||||
}
|
||||
}
|
||||
|
||||
return stored_obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the storage for this blog. Confirms that the data was saved
|
||||
* successfully.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {boolean} True if the data was saved successfully, false if it wasn't saved.
|
||||
*/
|
||||
function setStorage( stored_obj ) {
|
||||
var key;
|
||||
|
||||
if ( hasStorage && blog_id ) {
|
||||
key = 'wp-autosave-' + blog_id;
|
||||
sessionStorage.setItem( key, JSON.stringify( stored_obj ) );
|
||||
return sessionStorage.getItem( key ) !== null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the saved post data for the current post.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {boolean|Object} False if no storage or no data or the postData as an Object.
|
||||
*/
|
||||
function getSavedPostData() {
|
||||
var stored = getStorage();
|
||||
|
||||
if ( ! stored || ! post_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return stored[ 'post_' + post_id ] || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets (save or delete) post data in the storage.
|
||||
*
|
||||
* If stored_data evaluates to 'false' the storage key for the current post will be removed.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {Object|boolean|null} stored_data The post data to store or null/false/empty to delete the key.
|
||||
*
|
||||
* @return {boolean} True if data is stored, false if data was removed.
|
||||
*/
|
||||
function setData( stored_data ) {
|
||||
var stored = getStorage();
|
||||
|
||||
if ( ! stored || ! post_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( stored_data ) {
|
||||
stored[ 'post_' + post_id ] = stored_data;
|
||||
} else if ( stored.hasOwnProperty( 'post_' + post_id ) ) {
|
||||
delete stored[ 'post_' + post_id ];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return setStorage( stored );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets isSuspended to true.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function suspend() {
|
||||
isSuspended = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets isSuspended to false.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function resume() {
|
||||
isSuspended = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves post data for the current post.
|
||||
*
|
||||
* Runs on a 15 seconds interval, saves when there are differences in the post title or content.
|
||||
* When the optional data is provided, updates the last saved post data.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {Object} data The post data for saving, minimum 'post_title' and 'content'.
|
||||
*
|
||||
* @return {boolean} Returns true when data has been saved, otherwise it returns false.
|
||||
*/
|
||||
function save( data ) {
|
||||
var postData, compareString,
|
||||
result = false;
|
||||
|
||||
if ( isSuspended || ! hasStorage ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( data ) {
|
||||
postData = getSavedPostData() || {};
|
||||
$.extend( postData, data );
|
||||
} else {
|
||||
postData = getPostData('local');
|
||||
}
|
||||
|
||||
compareString = getCompareString( postData );
|
||||
|
||||
if ( typeof lastCompareString === 'undefined' ) {
|
||||
lastCompareString = initialCompareString;
|
||||
}
|
||||
|
||||
// If the content, title and excerpt did not change since the last save, don't save again.
|
||||
if ( compareString === lastCompareString ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postData.save_time = ( new Date() ).getTime();
|
||||
postData.status = $( '#post_status' ).val() || '';
|
||||
result = setData( postData );
|
||||
|
||||
if ( result ) {
|
||||
lastCompareString = compareString;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the auto save function.
|
||||
*
|
||||
* Checks whether the editor is active or not to use the editor events
|
||||
* to autosave, or uses the values from the elements to autosave.
|
||||
*
|
||||
* Runs on DOM ready.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function run() {
|
||||
post_id = $('#post_ID').val() || 0;
|
||||
|
||||
// Check if the local post data is different than the loaded post data.
|
||||
if ( $( '#wp-content-wrap' ).hasClass( 'tmce-active' ) ) {
|
||||
|
||||
/*
|
||||
* If TinyMCE loads first, check the post 1.5 seconds after it is ready.
|
||||
* By this time the content has been loaded in the editor and 'saved' to the textarea.
|
||||
* This prevents false positives.
|
||||
*/
|
||||
$document.on( 'tinymce-editor-init.autosave', function() {
|
||||
window.setTimeout( function() {
|
||||
checkPost();
|
||||
}, 1500 );
|
||||
});
|
||||
} else {
|
||||
checkPost();
|
||||
}
|
||||
|
||||
// Save every 15 seconds.
|
||||
intervalTimer = window.setInterval( save, 15000 );
|
||||
|
||||
$( 'form#post' ).on( 'submit.autosave-local', function() {
|
||||
var editor = getEditor(),
|
||||
post_id = $('#post_ID').val() || 0;
|
||||
|
||||
if ( editor && ! editor.isHidden() ) {
|
||||
|
||||
// Last onSubmit event in the editor, needs to run after the content has been moved to the textarea.
|
||||
editor.on( 'submit', function() {
|
||||
save({
|
||||
post_title: $( '#title' ).val() || '',
|
||||
content: $( '#content' ).val() || '',
|
||||
excerpt: $( '#excerpt' ).val() || ''
|
||||
});
|
||||
});
|
||||
} else {
|
||||
save({
|
||||
post_title: $( '#title' ).val() || '',
|
||||
content: $( '#content' ).val() || '',
|
||||
excerpt: $( '#excerpt' ).val() || ''
|
||||
});
|
||||
}
|
||||
|
||||
var secure = ( 'https:' === window.location.protocol );
|
||||
wpCookies.set( 'wp-saving-post', post_id + '-check', 24 * 60 * 60, false, false, secure );
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares 2 strings. Removes whitespaces in the strings before comparing them.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {string} str1 The first string.
|
||||
* @param {string} str2 The second string.
|
||||
* @return {boolean} True if the strings are the same.
|
||||
*/
|
||||
function compare( str1, str2 ) {
|
||||
function removeSpaces( string ) {
|
||||
return string.toString().replace(/[\x20\t\r\n\f]+/g, '');
|
||||
}
|
||||
|
||||
return ( removeSpaces( str1 || '' ) === removeSpaces( str2 || '' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the saved data for the current post (if any) is different than the
|
||||
* loaded post data on the screen.
|
||||
*
|
||||
* Shows a standard message letting the user restore the post data if different.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function checkPost() {
|
||||
var content, post_title, excerpt, $notice,
|
||||
postData = getSavedPostData(),
|
||||
cookie = wpCookies.get( 'wp-saving-post' ),
|
||||
$newerAutosaveNotice = $( '#has-newer-autosave' ).parent( '.notice' ),
|
||||
$headerEnd = $( '.wp-header-end' );
|
||||
|
||||
if ( cookie === post_id + '-saved' ) {
|
||||
wpCookies.remove( 'wp-saving-post' );
|
||||
// The post was saved properly, remove old data and bail.
|
||||
setData( false );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! postData ) {
|
||||
return;
|
||||
}
|
||||
|
||||
content = $( '#content' ).val() || '';
|
||||
post_title = $( '#title' ).val() || '';
|
||||
excerpt = $( '#excerpt' ).val() || '';
|
||||
|
||||
if ( compare( content, postData.content ) && compare( post_title, postData.post_title ) &&
|
||||
compare( excerpt, postData.excerpt ) ) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If '.wp-header-end' is found, append the notices after it otherwise
|
||||
* after the first h1 or h2 heading found within the main content.
|
||||
*/
|
||||
if ( ! $headerEnd.length ) {
|
||||
$headerEnd = $( '.wrap h1, .wrap h2' ).first();
|
||||
}
|
||||
|
||||
$notice = $( '#local-storage-notice' )
|
||||
.insertAfter( $headerEnd )
|
||||
.addClass( 'notice-warning' );
|
||||
|
||||
if ( $newerAutosaveNotice.length ) {
|
||||
|
||||
// If there is a "server" autosave notice, hide it.
|
||||
// The data in the session storage is either the same or newer.
|
||||
$newerAutosaveNotice.slideUp( 150, function() {
|
||||
$notice.slideDown( 150 );
|
||||
});
|
||||
} else {
|
||||
$notice.slideDown( 200 );
|
||||
}
|
||||
|
||||
$notice.find( '.restore-backup' ).on( 'click.autosave-local', function() {
|
||||
restorePost( postData );
|
||||
$notice.fadeTo( 250, 0, function() {
|
||||
$notice.slideUp( 150 );
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the current title, content and excerpt from postData.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {Object} postData The object containing all post data.
|
||||
*
|
||||
* @return {boolean} True if the post is restored.
|
||||
*/
|
||||
function restorePost( postData ) {
|
||||
var editor;
|
||||
|
||||
if ( postData ) {
|
||||
// Set the last saved data.
|
||||
lastCompareString = getCompareString( postData );
|
||||
|
||||
if ( $( '#title' ).val() !== postData.post_title ) {
|
||||
$( '#title' ).trigger( 'focus' ).val( postData.post_title || '' );
|
||||
}
|
||||
|
||||
$( '#excerpt' ).val( postData.excerpt || '' );
|
||||
editor = getEditor();
|
||||
|
||||
if ( editor && ! editor.isHidden() && typeof switchEditors !== 'undefined' ) {
|
||||
if ( editor.settings.wpautop && postData.content ) {
|
||||
postData.content = switchEditors.wpautop( postData.content );
|
||||
}
|
||||
|
||||
// Make sure there's an undo level in the editor.
|
||||
editor.undoManager.transact( function() {
|
||||
editor.setContent( postData.content || '' );
|
||||
editor.nodeChanged();
|
||||
});
|
||||
} else {
|
||||
|
||||
// Make sure the Text editor is selected.
|
||||
$( '#content-html' ).trigger( 'click' );
|
||||
$( '#content' ).trigger( 'focus' );
|
||||
|
||||
// Using document.execCommand() will let the user undo.
|
||||
document.execCommand( 'selectAll' );
|
||||
document.execCommand( 'insertText', false, postData.content || '' );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
blog_id = typeof window.autosaveL10n !== 'undefined' && window.autosaveL10n.blog_id;
|
||||
|
||||
/*
|
||||
* Check if the browser supports sessionStorage and it's not disabled,
|
||||
* then initialize and run checkPost().
|
||||
* Don't run if the post type supports neither 'editor' (textarea#content) nor 'excerpt'.
|
||||
*/
|
||||
if ( checkStorage() && blog_id && ( $('#content').length || $('#excerpt').length ) ) {
|
||||
$( run );
|
||||
}
|
||||
|
||||
return {
|
||||
hasStorage: hasStorage,
|
||||
getSavedPostData: getSavedPostData,
|
||||
save: save,
|
||||
suspend: suspend,
|
||||
resume: resume
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto saves the post on the server.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {Object} {
|
||||
* {
|
||||
* tempBlockSave: tempBlockSave,
|
||||
* triggerSave: triggerSave,
|
||||
* postChanged: postChanged,
|
||||
* suspend: suspend,
|
||||
* resume: resume
|
||||
* }
|
||||
* } The object all functions for autosave.
|
||||
*/
|
||||
function autosaveServer() {
|
||||
var _blockSave, _blockSaveTimer, previousCompareString, lastCompareString,
|
||||
nextRun = 0,
|
||||
isSuspended = false;
|
||||
|
||||
|
||||
/**
|
||||
* Blocks saving for the next 10 seconds.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function tempBlockSave() {
|
||||
_blockSave = true;
|
||||
window.clearTimeout( _blockSaveTimer );
|
||||
|
||||
_blockSaveTimer = window.setTimeout( function() {
|
||||
_blockSave = false;
|
||||
}, 10000 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets isSuspended to true.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function suspend() {
|
||||
isSuspended = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets isSuspended to false.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function resume() {
|
||||
isSuspended = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the autosave with the post data.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param {Object} data The post data.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function response( data ) {
|
||||
_schedule();
|
||||
_blockSave = false;
|
||||
lastCompareString = previousCompareString;
|
||||
previousCompareString = '';
|
||||
|
||||
$document.trigger( 'after-autosave', [data] );
|
||||
enableButtons();
|
||||
|
||||
if ( data.success ) {
|
||||
// No longer an auto-draft.
|
||||
$( '#auto_draft' ).val('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves immediately.
|
||||
*
|
||||
* Resets the timing and tells heartbeat to connect now.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function triggerSave() {
|
||||
nextRun = 0;
|
||||
wp.heartbeat.connectNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the post content in the textarea has changed since page load.
|
||||
*
|
||||
* This also happens when TinyMCE is active and editor.save() is triggered by
|
||||
* wp.autosave.getPostData().
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {boolean} True if the post has been changed.
|
||||
*/
|
||||
function postChanged() {
|
||||
var changed = false;
|
||||
|
||||
// If there are TinyMCE instances, loop through them.
|
||||
if ( window.tinymce ) {
|
||||
window.tinymce.each( [ 'content', 'excerpt' ], function( field ) {
|
||||
var editor = window.tinymce.get( field );
|
||||
|
||||
if ( ! editor || editor.isHidden() ) {
|
||||
if ( ( $( '#' + field ).val() || '' ) !== initialCompareData[ field ] ) {
|
||||
changed = true;
|
||||
// Break.
|
||||
return false;
|
||||
}
|
||||
} else if ( editor.isDirty() ) {
|
||||
changed = true;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
if ( ( $( '#title' ).val() || '' ) !== initialCompareData.post_title ) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
return getCompareString() !== initialCompareString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the post can be saved or not.
|
||||
*
|
||||
* If the post hasn't changed or it cannot be updated,
|
||||
* because the autosave is blocked or suspended, the function returns false.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {Object} Returns the post data.
|
||||
*/
|
||||
function save() {
|
||||
var postData, compareString;
|
||||
|
||||
// window.autosave() used for back-compat.
|
||||
if ( isSuspended || _blockSave || ! window.autosave() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ( new Date() ).getTime() < nextRun ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postData = getPostData();
|
||||
compareString = getCompareString( postData );
|
||||
|
||||
// First check.
|
||||
if ( typeof lastCompareString === 'undefined' ) {
|
||||
lastCompareString = initialCompareString;
|
||||
}
|
||||
|
||||
// No change.
|
||||
if ( compareString === lastCompareString ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
previousCompareString = compareString;
|
||||
tempBlockSave();
|
||||
disableButtons();
|
||||
|
||||
$document.trigger( 'wpcountwords', [ postData.content ] )
|
||||
.trigger( 'before-autosave', [ postData ] );
|
||||
|
||||
postData._wpnonce = $( '#_wpnonce' ).val() || '';
|
||||
|
||||
return postData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the next run, based on the autosave interval.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function _schedule() {
|
||||
nextRun = ( new Date() ).getTime() + ( autosaveL10n.autosaveInterval * 1000 ) || 60000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the autosaveData on the autosave heartbeat.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
$( function() {
|
||||
_schedule();
|
||||
}).on( 'heartbeat-send.autosave', function( event, data ) {
|
||||
var autosaveData = save();
|
||||
|
||||
if ( autosaveData ) {
|
||||
data.wp_autosave = autosaveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the autosave of the post with the autosave data on the autosave
|
||||
* heartbeat.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
}).on( 'heartbeat-tick.autosave', function( event, data ) {
|
||||
if ( data.wp_autosave ) {
|
||||
response( data.wp_autosave );
|
||||
}
|
||||
/**
|
||||
* Disables buttons and throws a notice when the connection is lost.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
}).on( 'heartbeat-connection-lost.autosave', function( event, error, status ) {
|
||||
|
||||
// When connection is lost, keep user from submitting changes.
|
||||
if ( 'timeout' === error || 603 === status ) {
|
||||
var $notice = $('#lost-connection-notice');
|
||||
|
||||
if ( ! wp.autosave.local.hasStorage ) {
|
||||
$notice.find('.hide-if-no-sessionstorage').hide();
|
||||
}
|
||||
|
||||
$notice.show();
|
||||
disableButtons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables buttons when the connection is restored.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
}).on( 'heartbeat-connection-restored.autosave', function() {
|
||||
$('#lost-connection-notice').hide();
|
||||
enableButtons();
|
||||
});
|
||||
|
||||
return {
|
||||
tempBlockSave: tempBlockSave,
|
||||
triggerSave: triggerSave,
|
||||
postChanged: postChanged,
|
||||
suspend: suspend,
|
||||
resume: resume
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the autosave time out.
|
||||
*
|
||||
* Wait for TinyMCE to initialize plus 1 second. for any external css to finish loading,
|
||||
* then save to the textarea before setting initialCompareString.
|
||||
* This avoids any insignificant differences between the initial textarea content and the content
|
||||
* extracted from the editor.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
$( function() {
|
||||
// Set the initial compare string in case TinyMCE is not used or not loaded first.
|
||||
setInitialCompare();
|
||||
}).on( 'tinymce-editor-init.autosave', function( event, editor ) {
|
||||
// Reset the initialCompare data after the TinyMCE instances have been initialized.
|
||||
if ( 'content' === editor.id || 'excerpt' === editor.id ) {
|
||||
window.setTimeout( function() {
|
||||
editor.save();
|
||||
setInitialCompare();
|
||||
}, 1000 );
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getPostData: getPostData,
|
||||
getCompareString: getCompareString,
|
||||
disableButtons: disableButtons,
|
||||
enableButtons: enableButtons,
|
||||
local: autosaveLocal(),
|
||||
server: autosaveServer()
|
||||
};
|
||||
}
|
||||
|
||||
/** @namespace wp */
|
||||
window.wp = window.wp || {};
|
||||
window.wp.autosave = autosave();
|
||||
|
||||
}( jQuery, window ));
|
||||
+2
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,890 @@
|
||||
/*!
|
||||
* clipboard.js v2.0.11
|
||||
* https://clipboardjs.com/
|
||||
*
|
||||
* Licensed MIT © Zeno Rocha
|
||||
*/
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define([], factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["ClipboardJS"] = factory();
|
||||
else
|
||||
root["ClipboardJS"] = factory();
|
||||
})(this, function() {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 686:
|
||||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
// EXPORTS
|
||||
__webpack_require__.d(__webpack_exports__, {
|
||||
"default": function() { return /* binding */ clipboard; }
|
||||
});
|
||||
|
||||
// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js
|
||||
var tiny_emitter = __webpack_require__(279);
|
||||
var tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);
|
||||
// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js
|
||||
var listen = __webpack_require__(370);
|
||||
var listen_default = /*#__PURE__*/__webpack_require__.n(listen);
|
||||
// EXTERNAL MODULE: ./node_modules/select/src/select.js
|
||||
var src_select = __webpack_require__(817);
|
||||
var select_default = /*#__PURE__*/__webpack_require__.n(src_select);
|
||||
;// CONCATENATED MODULE: ./src/common/command.js
|
||||
/**
|
||||
* Executes a given operation type.
|
||||
* @param {String} type
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function command(type) {
|
||||
try {
|
||||
return document.execCommand(type);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
;// CONCATENATED MODULE: ./src/actions/cut.js
|
||||
|
||||
|
||||
/**
|
||||
* Cut action wrapper.
|
||||
* @param {String|HTMLElement} target
|
||||
* @return {String}
|
||||
*/
|
||||
|
||||
var ClipboardActionCut = function ClipboardActionCut(target) {
|
||||
var selectedText = select_default()(target);
|
||||
command('cut');
|
||||
return selectedText;
|
||||
};
|
||||
|
||||
/* harmony default export */ var actions_cut = (ClipboardActionCut);
|
||||
;// CONCATENATED MODULE: ./src/common/create-fake-element.js
|
||||
/**
|
||||
* Creates a fake textarea element with a value.
|
||||
* @param {String} value
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
function createFakeElement(value) {
|
||||
var isRTL = document.documentElement.getAttribute('dir') === 'rtl';
|
||||
var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS
|
||||
|
||||
fakeElement.style.fontSize = '12pt'; // Reset box model
|
||||
|
||||
fakeElement.style.border = '0';
|
||||
fakeElement.style.padding = '0';
|
||||
fakeElement.style.margin = '0'; // Move element out of screen horizontally
|
||||
|
||||
fakeElement.style.position = 'absolute';
|
||||
fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically
|
||||
|
||||
var yPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||
fakeElement.style.top = "".concat(yPosition, "px");
|
||||
fakeElement.setAttribute('readonly', '');
|
||||
fakeElement.value = value;
|
||||
return fakeElement;
|
||||
}
|
||||
;// CONCATENATED MODULE: ./src/actions/copy.js
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create fake copy action wrapper using a fake element.
|
||||
* @param {String} target
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
*/
|
||||
|
||||
var fakeCopyAction = function fakeCopyAction(value, options) {
|
||||
var fakeElement = createFakeElement(value);
|
||||
options.container.appendChild(fakeElement);
|
||||
var selectedText = select_default()(fakeElement);
|
||||
command('copy');
|
||||
fakeElement.remove();
|
||||
return selectedText;
|
||||
};
|
||||
/**
|
||||
* Copy action wrapper.
|
||||
* @param {String|HTMLElement} target
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
*/
|
||||
|
||||
|
||||
var ClipboardActionCopy = function ClipboardActionCopy(target) {
|
||||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
||||
container: document.body
|
||||
};
|
||||
var selectedText = '';
|
||||
|
||||
if (typeof target === 'string') {
|
||||
selectedText = fakeCopyAction(target, options);
|
||||
} else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {
|
||||
// If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
|
||||
selectedText = fakeCopyAction(target.value, options);
|
||||
} else {
|
||||
selectedText = select_default()(target);
|
||||
command('copy');
|
||||
}
|
||||
|
||||
return selectedText;
|
||||
};
|
||||
|
||||
/* harmony default export */ var actions_copy = (ClipboardActionCopy);
|
||||
;// CONCATENATED MODULE: ./src/actions/default.js
|
||||
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inner function which performs selection from either `text` or `target`
|
||||
* properties and then executes copy or cut operations.
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
var ClipboardActionDefault = function ClipboardActionDefault() {
|
||||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
// Defines base properties passed from constructor.
|
||||
var _options$action = options.action,
|
||||
action = _options$action === void 0 ? 'copy' : _options$action,
|
||||
container = options.container,
|
||||
target = options.target,
|
||||
text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.
|
||||
|
||||
if (action !== 'copy' && action !== 'cut') {
|
||||
throw new Error('Invalid "action" value, use either "copy" or "cut"');
|
||||
} // Sets the `target` property using an element that will be have its content copied.
|
||||
|
||||
|
||||
if (target !== undefined) {
|
||||
if (target && _typeof(target) === 'object' && target.nodeType === 1) {
|
||||
if (action === 'copy' && target.hasAttribute('disabled')) {
|
||||
throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
|
||||
}
|
||||
|
||||
if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
|
||||
throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid "target" value, use a valid Element');
|
||||
}
|
||||
} // Define selection strategy based on `text` property.
|
||||
|
||||
|
||||
if (text) {
|
||||
return actions_copy(text, {
|
||||
container: container
|
||||
});
|
||||
} // Defines which selection strategy based on `target` property.
|
||||
|
||||
|
||||
if (target) {
|
||||
return action === 'cut' ? actions_cut(target) : actions_copy(target, {
|
||||
container: container
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/* harmony default export */ var actions_default = (ClipboardActionDefault);
|
||||
;// CONCATENATED MODULE: ./src/clipboard.js
|
||||
function clipboard_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return clipboard_typeof(obj); }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||||
|
||||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||||
|
||||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
||||
|
||||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
||||
|
||||
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
||||
|
||||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
||||
|
||||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
||||
|
||||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to retrieve attribute value.
|
||||
* @param {String} suffix
|
||||
* @param {Element} element
|
||||
*/
|
||||
|
||||
function getAttributeValue(suffix, element) {
|
||||
var attribute = "data-clipboard-".concat(suffix);
|
||||
|
||||
if (!element.hasAttribute(attribute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return element.getAttribute(attribute);
|
||||
}
|
||||
/**
|
||||
* Base class which takes one or more elements, adds event listeners to them,
|
||||
* and instantiates a new `ClipboardAction` on each click.
|
||||
*/
|
||||
|
||||
|
||||
var Clipboard = /*#__PURE__*/function (_Emitter) {
|
||||
_inherits(Clipboard, _Emitter);
|
||||
|
||||
var _super = _createSuper(Clipboard);
|
||||
|
||||
/**
|
||||
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
|
||||
* @param {Object} options
|
||||
*/
|
||||
function Clipboard(trigger, options) {
|
||||
var _this;
|
||||
|
||||
_classCallCheck(this, Clipboard);
|
||||
|
||||
_this = _super.call(this);
|
||||
|
||||
_this.resolveOptions(options);
|
||||
|
||||
_this.listenClick(trigger);
|
||||
|
||||
return _this;
|
||||
}
|
||||
/**
|
||||
* Defines if attributes would be resolved using internal setter functions
|
||||
* or custom functions that were passed in the constructor.
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
|
||||
_createClass(Clipboard, [{
|
||||
key: "resolveOptions",
|
||||
value: function resolveOptions() {
|
||||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
|
||||
this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
|
||||
this.text = typeof options.text === 'function' ? options.text : this.defaultText;
|
||||
this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;
|
||||
}
|
||||
/**
|
||||
* Adds a click event listener to the passed trigger.
|
||||
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "listenClick",
|
||||
value: function listenClick(trigger) {
|
||||
var _this2 = this;
|
||||
|
||||
this.listener = listen_default()(trigger, 'click', function (e) {
|
||||
return _this2.onClick(e);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Defines a new `ClipboardAction` on each click event.
|
||||
* @param {Event} e
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "onClick",
|
||||
value: function onClick(e) {
|
||||
var trigger = e.delegateTarget || e.currentTarget;
|
||||
var action = this.action(trigger) || 'copy';
|
||||
var text = actions_default({
|
||||
action: action,
|
||||
container: this.container,
|
||||
target: this.target(trigger),
|
||||
text: this.text(trigger)
|
||||
}); // Fires an event based on the copy operation result.
|
||||
|
||||
this.emit(text ? 'success' : 'error', {
|
||||
action: action,
|
||||
text: text,
|
||||
trigger: trigger,
|
||||
clearSelection: function clearSelection() {
|
||||
if (trigger) {
|
||||
trigger.focus();
|
||||
}
|
||||
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Default `action` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "defaultAction",
|
||||
value: function defaultAction(trigger) {
|
||||
return getAttributeValue('action', trigger);
|
||||
}
|
||||
/**
|
||||
* Default `target` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "defaultTarget",
|
||||
value: function defaultTarget(trigger) {
|
||||
var selector = getAttributeValue('target', trigger);
|
||||
|
||||
if (selector) {
|
||||
return document.querySelector(selector);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Allow fire programmatically a copy action
|
||||
* @param {String|HTMLElement} target
|
||||
* @param {Object} options
|
||||
* @returns Text copied.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "defaultText",
|
||||
|
||||
/**
|
||||
* Default `text` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
value: function defaultText(trigger) {
|
||||
return getAttributeValue('text', trigger);
|
||||
}
|
||||
/**
|
||||
* Destroy lifecycle.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "destroy",
|
||||
value: function destroy() {
|
||||
this.listener.destroy();
|
||||
}
|
||||
}], [{
|
||||
key: "copy",
|
||||
value: function copy(target) {
|
||||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
||||
container: document.body
|
||||
};
|
||||
return actions_copy(target, options);
|
||||
}
|
||||
/**
|
||||
* Allow fire programmatically a cut action
|
||||
* @param {String|HTMLElement} target
|
||||
* @returns Text cutted.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "cut",
|
||||
value: function cut(target) {
|
||||
return actions_cut(target);
|
||||
}
|
||||
/**
|
||||
* Returns the support of the given action, or all actions if no action is
|
||||
* given.
|
||||
* @param {String} [action]
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "isSupported",
|
||||
value: function isSupported() {
|
||||
var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];
|
||||
var actions = typeof action === 'string' ? [action] : action;
|
||||
var support = !!document.queryCommandSupported;
|
||||
actions.forEach(function (action) {
|
||||
support = support && !!document.queryCommandSupported(action);
|
||||
});
|
||||
return support;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Clipboard;
|
||||
}((tiny_emitter_default()));
|
||||
|
||||
/* harmony default export */ var clipboard = (Clipboard);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 828:
|
||||
/***/ (function(module) {
|
||||
|
||||
var DOCUMENT_NODE_TYPE = 9;
|
||||
|
||||
/**
|
||||
* A polyfill for Element.matches()
|
||||
*/
|
||||
if (typeof Element !== 'undefined' && !Element.prototype.matches) {
|
||||
var proto = Element.prototype;
|
||||
|
||||
proto.matches = proto.matchesSelector ||
|
||||
proto.mozMatchesSelector ||
|
||||
proto.msMatchesSelector ||
|
||||
proto.oMatchesSelector ||
|
||||
proto.webkitMatchesSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the closest parent that matches a selector.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @param {String} selector
|
||||
* @return {Function}
|
||||
*/
|
||||
function closest (element, selector) {
|
||||
while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
|
||||
if (typeof element.matches === 'function' &&
|
||||
element.matches(selector)) {
|
||||
return element;
|
||||
}
|
||||
element = element.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = closest;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 438:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var closest = __webpack_require__(828);
|
||||
|
||||
/**
|
||||
* Delegates event to a selector.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @param {String} selector
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @param {Boolean} useCapture
|
||||
* @return {Object}
|
||||
*/
|
||||
function _delegate(element, selector, type, callback, useCapture) {
|
||||
var listenerFn = listener.apply(this, arguments);
|
||||
|
||||
element.addEventListener(type, listenerFn, useCapture);
|
||||
|
||||
return {
|
||||
destroy: function() {
|
||||
element.removeEventListener(type, listenerFn, useCapture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates event to a selector.
|
||||
*
|
||||
* @param {Element|String|Array} [elements]
|
||||
* @param {String} selector
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @param {Boolean} useCapture
|
||||
* @return {Object}
|
||||
*/
|
||||
function delegate(elements, selector, type, callback, useCapture) {
|
||||
// Handle the regular Element usage
|
||||
if (typeof elements.addEventListener === 'function') {
|
||||
return _delegate.apply(null, arguments);
|
||||
}
|
||||
|
||||
// Handle Element-less usage, it defaults to global delegation
|
||||
if (typeof type === 'function') {
|
||||
// Use `document` as the first parameter, then apply arguments
|
||||
// This is a short way to .unshift `arguments` without running into deoptimizations
|
||||
return _delegate.bind(null, document).apply(null, arguments);
|
||||
}
|
||||
|
||||
// Handle Selector-based usage
|
||||
if (typeof elements === 'string') {
|
||||
elements = document.querySelectorAll(elements);
|
||||
}
|
||||
|
||||
// Handle Array-like based usage
|
||||
return Array.prototype.map.call(elements, function (element) {
|
||||
return _delegate(element, selector, type, callback, useCapture);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds closest match and invokes callback.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @param {String} selector
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @return {Function}
|
||||
*/
|
||||
function listener(element, selector, type, callback) {
|
||||
return function(e) {
|
||||
e.delegateTarget = closest(e.target, selector);
|
||||
|
||||
if (e.delegateTarget) {
|
||||
callback.call(element, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = delegate;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 879:
|
||||
/***/ (function(__unused_webpack_module, exports) {
|
||||
|
||||
/**
|
||||
* Check if argument is a HTML element.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
exports.node = function(value) {
|
||||
return value !== undefined
|
||||
&& value instanceof HTMLElement
|
||||
&& value.nodeType === 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if argument is a list of HTML elements.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
exports.nodeList = function(value) {
|
||||
var type = Object.prototype.toString.call(value);
|
||||
|
||||
return value !== undefined
|
||||
&& (type === '[object NodeList]' || type === '[object HTMLCollection]')
|
||||
&& ('length' in value)
|
||||
&& (value.length === 0 || exports.node(value[0]));
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if argument is a string.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
exports.string = function(value) {
|
||||
return typeof value === 'string'
|
||||
|| value instanceof String;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if argument is a function.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
exports.fn = function(value) {
|
||||
var type = Object.prototype.toString.call(value);
|
||||
|
||||
return type === '[object Function]';
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 370:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var is = __webpack_require__(879);
|
||||
var delegate = __webpack_require__(438);
|
||||
|
||||
/**
|
||||
* Validates all params and calls the right
|
||||
* listener function based on its target type.
|
||||
*
|
||||
* @param {String|HTMLElement|HTMLCollection|NodeList} target
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @return {Object}
|
||||
*/
|
||||
function listen(target, type, callback) {
|
||||
if (!target && !type && !callback) {
|
||||
throw new Error('Missing required arguments');
|
||||
}
|
||||
|
||||
if (!is.string(type)) {
|
||||
throw new TypeError('Second argument must be a String');
|
||||
}
|
||||
|
||||
if (!is.fn(callback)) {
|
||||
throw new TypeError('Third argument must be a Function');
|
||||
}
|
||||
|
||||
if (is.node(target)) {
|
||||
return listenNode(target, type, callback);
|
||||
}
|
||||
else if (is.nodeList(target)) {
|
||||
return listenNodeList(target, type, callback);
|
||||
}
|
||||
else if (is.string(target)) {
|
||||
return listenSelector(target, type, callback);
|
||||
}
|
||||
else {
|
||||
throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener to a HTML element
|
||||
* and returns a remove listener function.
|
||||
*
|
||||
* @param {HTMLElement} node
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @return {Object}
|
||||
*/
|
||||
function listenNode(node, type, callback) {
|
||||
node.addEventListener(type, callback);
|
||||
|
||||
return {
|
||||
destroy: function() {
|
||||
node.removeEventListener(type, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event listener to a list of HTML elements
|
||||
* and returns a remove listener function.
|
||||
*
|
||||
* @param {NodeList|HTMLCollection} nodeList
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @return {Object}
|
||||
*/
|
||||
function listenNodeList(nodeList, type, callback) {
|
||||
Array.prototype.forEach.call(nodeList, function(node) {
|
||||
node.addEventListener(type, callback);
|
||||
});
|
||||
|
||||
return {
|
||||
destroy: function() {
|
||||
Array.prototype.forEach.call(nodeList, function(node) {
|
||||
node.removeEventListener(type, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event listener to a selector
|
||||
* and returns a remove listener function.
|
||||
*
|
||||
* @param {String} selector
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @return {Object}
|
||||
*/
|
||||
function listenSelector(selector, type, callback) {
|
||||
return delegate(document.body, selector, type, callback);
|
||||
}
|
||||
|
||||
module.exports = listen;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 817:
|
||||
/***/ (function(module) {
|
||||
|
||||
function select(element) {
|
||||
var selectedText;
|
||||
|
||||
if (element.nodeName === 'SELECT') {
|
||||
element.focus();
|
||||
|
||||
selectedText = element.value;
|
||||
}
|
||||
else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
|
||||
var isReadOnly = element.hasAttribute('readonly');
|
||||
|
||||
if (!isReadOnly) {
|
||||
element.setAttribute('readonly', '');
|
||||
}
|
||||
|
||||
element.select();
|
||||
element.setSelectionRange(0, element.value.length);
|
||||
|
||||
if (!isReadOnly) {
|
||||
element.removeAttribute('readonly');
|
||||
}
|
||||
|
||||
selectedText = element.value;
|
||||
}
|
||||
else {
|
||||
if (element.hasAttribute('contenteditable')) {
|
||||
element.focus();
|
||||
}
|
||||
|
||||
var selection = window.getSelection();
|
||||
var range = document.createRange();
|
||||
|
||||
range.selectNodeContents(element);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
|
||||
selectedText = selection.toString();
|
||||
}
|
||||
|
||||
return selectedText;
|
||||
}
|
||||
|
||||
module.exports = select;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 279:
|
||||
/***/ (function(module) {
|
||||
|
||||
function E () {
|
||||
// Keep this empty so it's easier to inherit from
|
||||
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
|
||||
}
|
||||
|
||||
E.prototype = {
|
||||
on: function (name, callback, ctx) {
|
||||
var e = this.e || (this.e = {});
|
||||
|
||||
(e[name] || (e[name] = [])).push({
|
||||
fn: callback,
|
||||
ctx: ctx
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
once: function (name, callback, ctx) {
|
||||
var self = this;
|
||||
function listener () {
|
||||
self.off(name, listener);
|
||||
callback.apply(ctx, arguments);
|
||||
};
|
||||
|
||||
listener._ = callback
|
||||
return this.on(name, listener, ctx);
|
||||
},
|
||||
|
||||
emit: function (name) {
|
||||
var data = [].slice.call(arguments, 1);
|
||||
var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
|
||||
var i = 0;
|
||||
var len = evtArr.length;
|
||||
|
||||
for (i; i < len; i++) {
|
||||
evtArr[i].fn.apply(evtArr[i].ctx, data);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
off: function (name, callback) {
|
||||
var e = this.e || (this.e = {});
|
||||
var evts = e[name];
|
||||
var liveEvents = [];
|
||||
|
||||
if (evts && callback) {
|
||||
for (var i = 0, len = evts.length; i < len; i++) {
|
||||
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
|
||||
liveEvents.push(evts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove event from queue to prevent memory leak
|
||||
// Suggested by https://github.com/lazd
|
||||
// Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
|
||||
|
||||
(liveEvents.length)
|
||||
? e[name] = liveEvents
|
||||
: delete e[name];
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = E;
|
||||
module.exports.TinyEmitter = E;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(__webpack_module_cache__[moduleId]) {
|
||||
/******/ return __webpack_module_cache__[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ // module exports must be returned from runtime so entry inlining is disabled
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(686);
|
||||
/******/ })()
|
||||
.default;
|
||||
});
|
||||
+2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
// JSHINT has some GPL Compatability issues, so we are faking it out and using esprima for validation
|
||||
// Based on https://github.com/jquery/esprima/blob/gh-pages/demo/validate.js which is MIT licensed
|
||||
|
||||
var fakeJSHINT = new function() {
|
||||
var syntax, errors;
|
||||
var that = this;
|
||||
this.data = [];
|
||||
this.convertError = function( error ){
|
||||
return {
|
||||
line: error.lineNumber,
|
||||
character: error.column,
|
||||
reason: error.description,
|
||||
code: 'E'
|
||||
};
|
||||
};
|
||||
this.parse = function( code ){
|
||||
try {
|
||||
syntax = window.esprima.parse(code, { tolerant: true, loc: true });
|
||||
errors = syntax.errors;
|
||||
if ( errors.length > 0 ) {
|
||||
for ( var i = 0; i < errors.length; i++) {
|
||||
var error = errors[i];
|
||||
that.data.push( that.convertError( error ) );
|
||||
}
|
||||
} else {
|
||||
that.data = [];
|
||||
}
|
||||
} catch (e) {
|
||||
that.data.push( that.convertError( e ) );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
window.JSHINT = function( text ){
|
||||
fakeJSHINT.parse( text );
|
||||
};
|
||||
window.JSHINT.data = function(){
|
||||
return {
|
||||
errors: fakeJSHINT.data
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* global HTMLHint */
|
||||
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1] }] */
|
||||
HTMLHint.addRule({
|
||||
id: 'kses',
|
||||
description: 'Element or attribute cannot be used.',
|
||||
init: function( parser, reporter, options ) {
|
||||
'use strict';
|
||||
|
||||
var self = this;
|
||||
parser.addListener( 'tagstart', function( event ) {
|
||||
var attr, col, attrName, allowedAttributes, i, len, tagName;
|
||||
|
||||
tagName = event.tagName.toLowerCase();
|
||||
if ( ! options[ tagName ] ) {
|
||||
reporter.error( 'Tag <' + event.tagName + '> is not allowed.', event.line, event.col, self, event.raw );
|
||||
return;
|
||||
}
|
||||
|
||||
allowedAttributes = options[ tagName ];
|
||||
col = event.col + event.tagName.length + 1;
|
||||
for ( i = 0, len = event.attrs.length; i < len; i++ ) {
|
||||
attr = event.attrs[ i ];
|
||||
attrName = attr.name.toLowerCase();
|
||||
if ( ! allowedAttributes[ attrName ] ) {
|
||||
reporter.error( 'Tag attribute [' + attr.raw + ' ] is not allowed.', event.line, col + attr.index, self, attr.raw );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,432 @@
|
||||
/* Jison generated parser */
|
||||
var jsonlint = (function(){
|
||||
var parser = {trace: function trace() { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
|
||||
terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
|
||||
productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
|
||||
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
switch (yystate) {
|
||||
case 1: // replace escaped characters with actual character
|
||||
this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
|
||||
.replace(/\\n/g,'\n')
|
||||
.replace(/\\r/g,'\r')
|
||||
.replace(/\\t/g,'\t')
|
||||
.replace(/\\v/g,'\v')
|
||||
.replace(/\\f/g,'\f')
|
||||
.replace(/\\b/g,'\b');
|
||||
|
||||
break;
|
||||
case 2:this.$ = Number(yytext);
|
||||
break;
|
||||
case 3:this.$ = null;
|
||||
break;
|
||||
case 4:this.$ = true;
|
||||
break;
|
||||
case 5:this.$ = false;
|
||||
break;
|
||||
case 6:return this.$ = $$[$0-1];
|
||||
break;
|
||||
case 13:this.$ = {};
|
||||
break;
|
||||
case 14:this.$ = $$[$0-1];
|
||||
break;
|
||||
case 15:this.$ = [$$[$0-2], $$[$0]];
|
||||
break;
|
||||
case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
|
||||
break;
|
||||
case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];
|
||||
break;
|
||||
case 18:this.$ = [];
|
||||
break;
|
||||
case 19:this.$ = $$[$0-1];
|
||||
break;
|
||||
case 20:this.$ = [$$[$0]];
|
||||
break;
|
||||
case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
|
||||
break;
|
||||
}
|
||||
},
|
||||
table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],
|
||||
defaultActions: {16:[2,6]},
|
||||
parseError: function parseError(str, hash) {
|
||||
throw new Error(str);
|
||||
},
|
||||
parse: function parse(input) {
|
||||
var self = this,
|
||||
stack = [0],
|
||||
vstack = [null], // semantic value stack
|
||||
lstack = [], // location stack
|
||||
table = this.table,
|
||||
yytext = '',
|
||||
yylineno = 0,
|
||||
yyleng = 0,
|
||||
recovering = 0,
|
||||
TERROR = 2,
|
||||
EOF = 1;
|
||||
|
||||
//this.reductionCount = this.shiftCount = 0;
|
||||
|
||||
this.lexer.setInput(input);
|
||||
this.lexer.yy = this.yy;
|
||||
this.yy.lexer = this.lexer;
|
||||
if (typeof this.lexer.yylloc == 'undefined')
|
||||
this.lexer.yylloc = {};
|
||||
var yyloc = this.lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
|
||||
if (typeof this.yy.parseError === 'function')
|
||||
this.parseError = this.yy.parseError;
|
||||
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2*n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
}
|
||||
|
||||
function lex() {
|
||||
var token;
|
||||
token = self.lexer.lex() || 1; // $end = 1
|
||||
// if token isn't its numeric value, convert
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
|
||||
while (true) {
|
||||
// retreive state number from top of stack
|
||||
state = stack[stack.length-1];
|
||||
|
||||
// use default actions if available
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
} else {
|
||||
if (symbol == null)
|
||||
symbol = lex();
|
||||
// read action for current state and first input
|
||||
action = table[state] && table[state][symbol];
|
||||
}
|
||||
|
||||
// handle parse error
|
||||
_handle_error:
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
|
||||
if (!recovering) {
|
||||
// Report error
|
||||
expected = [];
|
||||
for (p in table[state]) if (this.terminals_[p] && p > 2) {
|
||||
expected.push("'"+this.terminals_[p]+"'");
|
||||
}
|
||||
var errStr = '';
|
||||
if (this.lexer.showPosition) {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
|
||||
} else {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
|
||||
(symbol == 1 /*EOF*/ ? "end of input" :
|
||||
("'"+(this.terminals_[symbol] || symbol)+"'"));
|
||||
}
|
||||
this.parseError(errStr,
|
||||
{text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
|
||||
}
|
||||
|
||||
// just recovered from another error
|
||||
if (recovering == 3) {
|
||||
if (symbol == EOF) {
|
||||
throw new Error(errStr || 'Parsing halted.');
|
||||
}
|
||||
|
||||
// discard current lookahead and grab another
|
||||
yyleng = this.lexer.yyleng;
|
||||
yytext = this.lexer.yytext;
|
||||
yylineno = this.lexer.yylineno;
|
||||
yyloc = this.lexer.yylloc;
|
||||
symbol = lex();
|
||||
}
|
||||
|
||||
// try to recover from error
|
||||
while (1) {
|
||||
// check for error recovery rule in this state
|
||||
if ((TERROR.toString()) in table[state]) {
|
||||
break;
|
||||
}
|
||||
if (state == 0) {
|
||||
throw new Error(errStr || 'Parsing halted.');
|
||||
}
|
||||
popStack(1);
|
||||
state = stack[stack.length-1];
|
||||
}
|
||||
|
||||
preErrorSymbol = symbol; // save the lookahead token
|
||||
symbol = TERROR; // insert generic error symbol as new lookahead
|
||||
state = stack[stack.length-1];
|
||||
action = table[state] && table[state][TERROR];
|
||||
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
|
||||
}
|
||||
|
||||
// this shouldn't happen, unless resolve defaults are off
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
|
||||
}
|
||||
|
||||
switch (action[0]) {
|
||||
|
||||
case 1: // shift
|
||||
//this.shiftCount++;
|
||||
|
||||
stack.push(symbol);
|
||||
vstack.push(this.lexer.yytext);
|
||||
lstack.push(this.lexer.yylloc);
|
||||
stack.push(action[1]); // push state
|
||||
symbol = null;
|
||||
if (!preErrorSymbol) { // normal execution/no error
|
||||
yyleng = this.lexer.yyleng;
|
||||
yytext = this.lexer.yytext;
|
||||
yylineno = this.lexer.yylineno;
|
||||
yyloc = this.lexer.yylloc;
|
||||
if (recovering > 0)
|
||||
recovering--;
|
||||
} else { // error just occurred, resume old lookahead f/ before error
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // reduce
|
||||
//this.reductionCount++;
|
||||
|
||||
len = this.productions_[action[1]][1];
|
||||
|
||||
// perform semantic action
|
||||
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
|
||||
// default location, uses first token for firsts, last for lasts
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length-(len||1)].first_line,
|
||||
last_line: lstack[lstack.length-1].last_line,
|
||||
first_column: lstack[lstack.length-(len||1)].first_column,
|
||||
last_column: lstack[lstack.length-1].last_column
|
||||
};
|
||||
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
|
||||
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
}
|
||||
|
||||
// pop off stack
|
||||
if (len) {
|
||||
stack = stack.slice(0,-1*len*2);
|
||||
vstack = vstack.slice(0, -1*len);
|
||||
lstack = lstack.slice(0, -1*len);
|
||||
}
|
||||
|
||||
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
// goto new state = table[STATE][NONTERMINAL]
|
||||
newState = table[stack[stack.length-2]][stack[stack.length-1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
|
||||
case 3: // accept
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}};
|
||||
/* Jison generated lexer */
|
||||
var lexer = (function(){
|
||||
var lexer = ({EOF:1,
|
||||
parseError:function parseError(str, hash) {
|
||||
if (this.yy.parseError) {
|
||||
this.yy.parseError(str, hash);
|
||||
} else {
|
||||
throw new Error(str);
|
||||
}
|
||||
},
|
||||
setInput:function (input) {
|
||||
this._input = input;
|
||||
this._more = this._less = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
|
||||
return this;
|
||||
},
|
||||
input:function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext+=ch;
|
||||
this.yyleng++;
|
||||
this.match+=ch;
|
||||
this.matched+=ch;
|
||||
var lines = ch.match(/\n/);
|
||||
if (lines) this.yylineno++;
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
},
|
||||
unput:function (ch) {
|
||||
this._input = ch + this._input;
|
||||
return this;
|
||||
},
|
||||
more:function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
},
|
||||
less:function (n) {
|
||||
this._input = this.match.slice(n) + this._input;
|
||||
},
|
||||
pastInput:function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
},
|
||||
upcomingInput:function () {
|
||||
var next = this.match;
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
}
|
||||
return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
|
||||
},
|
||||
showPosition:function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c+"^";
|
||||
},
|
||||
next:function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
}
|
||||
if (!this._input) this.done = true;
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index,
|
||||
col,
|
||||
lines;
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
for (var i=0;i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
if (!this.options.flex) break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
lines = match[0].match(/\n.*/g);
|
||||
if (lines) this.yylineno += lines.length;
|
||||
this.yylloc = {first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno+1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.yyleng = this.yytext.length;
|
||||
this._more = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
|
||||
if (this.done && this._input) this.done = false;
|
||||
if (token) return token;
|
||||
else return;
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
} else {
|
||||
this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
|
||||
{text: "", token: null, line: this.yylineno});
|
||||
}
|
||||
},
|
||||
lex:function lex() {
|
||||
var r = this.next();
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
} else {
|
||||
return this.lex();
|
||||
}
|
||||
},
|
||||
begin:function begin(condition) {
|
||||
this.conditionStack.push(condition);
|
||||
},
|
||||
popState:function popState() {
|
||||
return this.conditionStack.pop();
|
||||
},
|
||||
_currentRules:function _currentRules() {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
|
||||
},
|
||||
topState:function () {
|
||||
return this.conditionStack[this.conditionStack.length-2];
|
||||
},
|
||||
pushState:function begin(condition) {
|
||||
this.begin(condition);
|
||||
}});
|
||||
lexer.options = {};
|
||||
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
||||
|
||||
var YYSTATE=YY_START
|
||||
switch($avoiding_name_collisions) {
|
||||
case 0:/* skip whitespace */
|
||||
break;
|
||||
case 1:return 6
|
||||
break;
|
||||
case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
|
||||
break;
|
||||
case 3:return 17
|
||||
break;
|
||||
case 4:return 18
|
||||
break;
|
||||
case 5:return 23
|
||||
break;
|
||||
case 6:return 24
|
||||
break;
|
||||
case 7:return 22
|
||||
break;
|
||||
case 8:return 21
|
||||
break;
|
||||
case 9:return 10
|
||||
break;
|
||||
case 10:return 11
|
||||
break;
|
||||
case 11:return 8
|
||||
break;
|
||||
case 12:return 14
|
||||
break;
|
||||
case 13:return 'INVALID'
|
||||
break;
|
||||
}
|
||||
};
|
||||
lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/];
|
||||
lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}};
|
||||
|
||||
|
||||
;
|
||||
return lexer;})()
|
||||
parser.lexer = lexer;
|
||||
return parser;
|
||||
})();
|
||||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||||
exports.parser = jsonlint;
|
||||
exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); }
|
||||
exports.main = function commonjsMain(args) {
|
||||
if (!args[1])
|
||||
throw new Error('Usage: '+args[0]+' FILE');
|
||||
if (typeof process !== 'undefined') {
|
||||
var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
|
||||
} else {
|
||||
var cwd = require("file").path(require("file").cwd());
|
||||
var source = cwd.join(args[1]).read({charset: "utf-8"});
|
||||
}
|
||||
return exports.parser.parse(source);
|
||||
}
|
||||
if (typeof module !== 'undefined' && require.main === module) {
|
||||
exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,707 @@
|
||||
// ===================================================================
|
||||
// Author: Matt Kruse <matt@mattkruse.com>
|
||||
// WWW: http://www.mattkruse.com/
|
||||
//
|
||||
// NOTICE: You may use this code for any purpose, commercial or
|
||||
// private, without any further permission from the author. You may
|
||||
// remove this notice from your final code if you wish, however it is
|
||||
// appreciated by the author if at least my web site address is kept.
|
||||
//
|
||||
// You may *NOT* re-distribute this code in any way except through its
|
||||
// use. That means, you can include it in your product, or your web
|
||||
// site, or any other form where the code is actually being used. You
|
||||
// may not put the plain javascript up on your site for download or
|
||||
// include it in your javascript libraries for download.
|
||||
// If you wish to share this code with others, please just point them
|
||||
// to the URL instead.
|
||||
// Please DO NOT link directly to my .js files from your site. Copy
|
||||
// the files to your server and use them there. Thank you.
|
||||
// ===================================================================
|
||||
|
||||
|
||||
/* SOURCE FILE: AnchorPosition.js */
|
||||
|
||||
/*
|
||||
AnchorPosition.js
|
||||
Author: Matt Kruse
|
||||
Last modified: 10/11/02
|
||||
|
||||
DESCRIPTION: These functions find the position of an <A> tag in a document,
|
||||
so other elements can be positioned relative to it.
|
||||
|
||||
COMPATABILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small
|
||||
positioning errors - usually with Window positioning - occur on the
|
||||
Macintosh platform.
|
||||
|
||||
FUNCTIONS:
|
||||
getAnchorPosition(anchorname)
|
||||
Returns an Object() having .x and .y properties of the pixel coordinates
|
||||
of the upper-left corner of the anchor. Position is relative to the PAGE.
|
||||
|
||||
getAnchorWindowPosition(anchorname)
|
||||
Returns an Object() having .x and .y properties of the pixel coordinates
|
||||
of the upper-left corner of the anchor, relative to the WHOLE SCREEN.
|
||||
|
||||
NOTES:
|
||||
|
||||
1) For popping up separate browser windows, use getAnchorWindowPosition.
|
||||
Otherwise, use getAnchorPosition
|
||||
|
||||
2) Your anchor tag MUST contain both NAME and ID attributes which are the
|
||||
same. For example:
|
||||
<A NAME="test" ID="test"> </A>
|
||||
|
||||
3) There must be at least a space between <A> </A> for IE5.5 to see the
|
||||
anchor tag correctly. Do not do <A></A> with no space.
|
||||
*/
|
||||
|
||||
// getAnchorPosition(anchorname)
|
||||
// This function returns an object having .x and .y properties which are the coordinates
|
||||
// of the named anchor, relative to the page.
|
||||
function getAnchorPosition(anchorname) {
|
||||
// This function will return an Object with x and y properties
|
||||
var useWindow=false;
|
||||
var coordinates=new Object();
|
||||
var x=0,y=0;
|
||||
// Browser capability sniffing
|
||||
var use_gebi=false, use_css=false, use_layers=false;
|
||||
if (document.getElementById) { use_gebi=true; }
|
||||
else if (document.all) { use_css=true; }
|
||||
else if (document.layers) { use_layers=true; }
|
||||
// Logic to find position
|
||||
if (use_gebi && document.all) {
|
||||
x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
|
||||
y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
|
||||
}
|
||||
else if (use_gebi) {
|
||||
var o=document.getElementById(anchorname);
|
||||
x=AnchorPosition_getPageOffsetLeft(o);
|
||||
y=AnchorPosition_getPageOffsetTop(o);
|
||||
}
|
||||
else if (use_css) {
|
||||
x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
|
||||
y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
|
||||
}
|
||||
else if (use_layers) {
|
||||
var found=0;
|
||||
for (var i=0; i<document.anchors.length; i++) {
|
||||
if (document.anchors[i].name==anchorname) { found=1; break; }
|
||||
}
|
||||
if (found==0) {
|
||||
coordinates.x=0; coordinates.y=0; return coordinates;
|
||||
}
|
||||
x=document.anchors[i].x;
|
||||
y=document.anchors[i].y;
|
||||
}
|
||||
else {
|
||||
coordinates.x=0; coordinates.y=0; return coordinates;
|
||||
}
|
||||
coordinates.x=x;
|
||||
coordinates.y=y;
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
// getAnchorWindowPosition(anchorname)
|
||||
// This function returns an object having .x and .y properties which are the coordinates
|
||||
// of the named anchor, relative to the window
|
||||
function getAnchorWindowPosition(anchorname) {
|
||||
var coordinates=getAnchorPosition(anchorname);
|
||||
var x=0;
|
||||
var y=0;
|
||||
if (document.getElementById) {
|
||||
if (isNaN(window.screenX)) {
|
||||
x=coordinates.x-document.body.scrollLeft+window.screenLeft;
|
||||
y=coordinates.y-document.body.scrollTop+window.screenTop;
|
||||
}
|
||||
else {
|
||||
x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
|
||||
y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
|
||||
}
|
||||
}
|
||||
else if (document.all) {
|
||||
x=coordinates.x-document.body.scrollLeft+window.screenLeft;
|
||||
y=coordinates.y-document.body.scrollTop+window.screenTop;
|
||||
}
|
||||
else if (document.layers) {
|
||||
x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
|
||||
y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
|
||||
}
|
||||
coordinates.x=x;
|
||||
coordinates.y=y;
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
// Functions for IE to get position of an object
|
||||
function AnchorPosition_getPageOffsetLeft (el) {
|
||||
var ol=el.offsetLeft;
|
||||
while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
|
||||
return ol;
|
||||
}
|
||||
function AnchorPosition_getWindowOffsetLeft (el) {
|
||||
return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
|
||||
}
|
||||
function AnchorPosition_getPageOffsetTop (el) {
|
||||
var ot=el.offsetTop;
|
||||
while((el=el.offsetParent) != null) { ot += el.offsetTop; }
|
||||
return ot;
|
||||
}
|
||||
function AnchorPosition_getWindowOffsetTop (el) {
|
||||
return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
|
||||
}
|
||||
|
||||
/* SOURCE FILE: PopupWindow.js */
|
||||
|
||||
/*
|
||||
PopupWindow.js
|
||||
Author: Matt Kruse
|
||||
Last modified: 02/16/04
|
||||
|
||||
DESCRIPTION: This object allows you to easily and quickly popup a window
|
||||
in a certain place. The window can either be a DIV or a separate browser
|
||||
window.
|
||||
|
||||
COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
|
||||
positioning errors - usually with Window positioning - occur on the
|
||||
Macintosh platform. Due to bugs in Netscape 4.x, populating the popup
|
||||
window with <STYLE> tags may cause errors.
|
||||
|
||||
USAGE:
|
||||
// Create an object for a WINDOW popup
|
||||
var win = new PopupWindow();
|
||||
|
||||
// Create an object for a DIV window using the DIV named 'mydiv'
|
||||
var win = new PopupWindow('mydiv');
|
||||
|
||||
// Set the window to automatically hide itself when the user clicks
|
||||
// anywhere else on the page except the popup
|
||||
win.autoHide();
|
||||
|
||||
// Show the window relative to the anchor name passed in
|
||||
win.showPopup(anchorname);
|
||||
|
||||
// Hide the popup
|
||||
win.hidePopup();
|
||||
|
||||
// Set the size of the popup window (only applies to WINDOW popups
|
||||
win.setSize(width,height);
|
||||
|
||||
// Populate the contents of the popup window that will be shown. If you
|
||||
// change the contents while it is displayed, you will need to refresh()
|
||||
win.populate(string);
|
||||
|
||||
// set the URL of the window, rather than populating its contents
|
||||
// manually
|
||||
win.setUrl("http://www.site.com/");
|
||||
|
||||
// Refresh the contents of the popup
|
||||
win.refresh();
|
||||
|
||||
// Specify how many pixels to the right of the anchor the popup will appear
|
||||
win.offsetX = 50;
|
||||
|
||||
// Specify how many pixels below the anchor the popup will appear
|
||||
win.offsetY = 100;
|
||||
|
||||
NOTES:
|
||||
1) Requires the functions in AnchorPosition.js
|
||||
|
||||
2) Your anchor tag MUST contain both NAME and ID attributes which are the
|
||||
same. For example:
|
||||
<A NAME="test" ID="test"> </A>
|
||||
|
||||
3) There must be at least a space between <A> </A> for IE5.5 to see the
|
||||
anchor tag correctly. Do not do <A></A> with no space.
|
||||
|
||||
4) When a PopupWindow object is created, a handler for 'onmouseup' is
|
||||
attached to any event handler you may have already defined. Do NOT define
|
||||
an event handler for 'onmouseup' after you define a PopupWindow object or
|
||||
the autoHide() will not work correctly.
|
||||
*/
|
||||
|
||||
// Set the position of the popup window based on the anchor
|
||||
function PopupWindow_getXYPosition(anchorname) {
|
||||
var coordinates;
|
||||
if (this.type == "WINDOW") {
|
||||
coordinates = getAnchorWindowPosition(anchorname);
|
||||
}
|
||||
else {
|
||||
coordinates = getAnchorPosition(anchorname);
|
||||
}
|
||||
this.x = coordinates.x;
|
||||
this.y = coordinates.y;
|
||||
}
|
||||
// Set width/height of DIV/popup window
|
||||
function PopupWindow_setSize(width,height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
// Fill the window with contents
|
||||
function PopupWindow_populate(contents) {
|
||||
this.contents = contents;
|
||||
this.populated = false;
|
||||
}
|
||||
// Set the URL to go to
|
||||
function PopupWindow_setUrl(url) {
|
||||
this.url = url;
|
||||
}
|
||||
// Set the window popup properties
|
||||
function PopupWindow_setWindowProperties(props) {
|
||||
this.windowProperties = props;
|
||||
}
|
||||
// Refresh the displayed contents of the popup
|
||||
function PopupWindow_refresh() {
|
||||
if (this.divName != null) {
|
||||
// refresh the DIV object
|
||||
if (this.use_gebi) {
|
||||
document.getElementById(this.divName).innerHTML = this.contents;
|
||||
}
|
||||
else if (this.use_css) {
|
||||
document.all[this.divName].innerHTML = this.contents;
|
||||
}
|
||||
else if (this.use_layers) {
|
||||
var d = document.layers[this.divName];
|
||||
d.document.open();
|
||||
d.document.writeln(this.contents);
|
||||
d.document.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.popupWindow != null && !this.popupWindow.closed) {
|
||||
if (this.url!="") {
|
||||
this.popupWindow.location.href=this.url;
|
||||
}
|
||||
else {
|
||||
this.popupWindow.document.open();
|
||||
this.popupWindow.document.writeln(this.contents);
|
||||
this.popupWindow.document.close();
|
||||
}
|
||||
this.popupWindow.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Position and show the popup, relative to an anchor object
|
||||
function PopupWindow_showPopup(anchorname) {
|
||||
this.getXYPosition(anchorname);
|
||||
this.x += this.offsetX;
|
||||
this.y += this.offsetY;
|
||||
if (!this.populated && (this.contents != "")) {
|
||||
this.populated = true;
|
||||
this.refresh();
|
||||
}
|
||||
if (this.divName != null) {
|
||||
// Show the DIV object
|
||||
if (this.use_gebi) {
|
||||
document.getElementById(this.divName).style.left = this.x + "px";
|
||||
document.getElementById(this.divName).style.top = this.y;
|
||||
document.getElementById(this.divName).style.visibility = "visible";
|
||||
}
|
||||
else if (this.use_css) {
|
||||
document.all[this.divName].style.left = this.x;
|
||||
document.all[this.divName].style.top = this.y;
|
||||
document.all[this.divName].style.visibility = "visible";
|
||||
}
|
||||
else if (this.use_layers) {
|
||||
document.layers[this.divName].left = this.x;
|
||||
document.layers[this.divName].top = this.y;
|
||||
document.layers[this.divName].visibility = "visible";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.popupWindow == null || this.popupWindow.closed) {
|
||||
// If the popup window will go off-screen, move it so it doesn't
|
||||
if (this.x<0) { this.x=0; }
|
||||
if (this.y<0) { this.y=0; }
|
||||
if (screen && screen.availHeight) {
|
||||
if ((this.y + this.height) > screen.availHeight) {
|
||||
this.y = screen.availHeight - this.height;
|
||||
}
|
||||
}
|
||||
if (screen && screen.availWidth) {
|
||||
if ((this.x + this.width) > screen.availWidth) {
|
||||
this.x = screen.availWidth - this.width;
|
||||
}
|
||||
}
|
||||
var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
|
||||
this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
|
||||
}
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
// Hide the popup
|
||||
function PopupWindow_hidePopup() {
|
||||
if (this.divName != null) {
|
||||
if (this.use_gebi) {
|
||||
document.getElementById(this.divName).style.visibility = "hidden";
|
||||
}
|
||||
else if (this.use_css) {
|
||||
document.all[this.divName].style.visibility = "hidden";
|
||||
}
|
||||
else if (this.use_layers) {
|
||||
document.layers[this.divName].visibility = "hidden";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.popupWindow && !this.popupWindow.closed) {
|
||||
this.popupWindow.close();
|
||||
this.popupWindow = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pass an event and return whether or not it was the popup DIV that was clicked
|
||||
function PopupWindow_isClicked(e) {
|
||||
if (this.divName != null) {
|
||||
if (this.use_layers) {
|
||||
var clickX = e.pageX;
|
||||
var clickY = e.pageY;
|
||||
var t = document.layers[this.divName];
|
||||
if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
|
||||
return true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
else if (document.all) { // Need to hard-code this to trap IE for error-handling
|
||||
var t = window.event.srcElement;
|
||||
while (t.parentElement != null) {
|
||||
if (t.id==this.divName) {
|
||||
return true;
|
||||
}
|
||||
t = t.parentElement;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (this.use_gebi && e) {
|
||||
var t = e.originalTarget;
|
||||
while (t.parentNode != null) {
|
||||
if (t.id==this.divName) {
|
||||
return true;
|
||||
}
|
||||
t = t.parentNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check an onMouseDown event to see if we should hide
|
||||
function PopupWindow_hideIfNotClicked(e) {
|
||||
if (this.autoHideEnabled && !this.isClicked(e)) {
|
||||
this.hidePopup();
|
||||
}
|
||||
}
|
||||
// Call this to make the DIV disable automatically when mouse is clicked outside it
|
||||
function PopupWindow_autoHide() {
|
||||
this.autoHideEnabled = true;
|
||||
}
|
||||
// This global function checks all PopupWindow objects onmouseup to see if they should be hidden
|
||||
function PopupWindow_hidePopupWindows(e) {
|
||||
for (var i=0; i<popupWindowObjects.length; i++) {
|
||||
if (popupWindowObjects[i] != null) {
|
||||
var p = popupWindowObjects[i];
|
||||
p.hideIfNotClicked(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run this immediately to attach the event listener
|
||||
function PopupWindow_attachListener() {
|
||||
if (document.layers) {
|
||||
document.captureEvents(Event.MOUSEUP);
|
||||
}
|
||||
window.popupWindowOldEventListener = document.onmouseup;
|
||||
if (window.popupWindowOldEventListener != null) {
|
||||
document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
|
||||
}
|
||||
else {
|
||||
document.onmouseup = PopupWindow_hidePopupWindows;
|
||||
}
|
||||
}
|
||||
// CONSTRUCTOR for the PopupWindow object
|
||||
// Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
|
||||
function PopupWindow() {
|
||||
if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
|
||||
if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
|
||||
if (!window.listenerAttached) {
|
||||
window.listenerAttached = true;
|
||||
PopupWindow_attachListener();
|
||||
}
|
||||
this.index = popupWindowIndex++;
|
||||
popupWindowObjects[this.index] = this;
|
||||
this.divName = null;
|
||||
this.popupWindow = null;
|
||||
this.width=0;
|
||||
this.height=0;
|
||||
this.populated = false;
|
||||
this.visible = false;
|
||||
this.autoHideEnabled = false;
|
||||
|
||||
this.contents = "";
|
||||
this.url="";
|
||||
this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
|
||||
if (arguments.length>0) {
|
||||
this.type="DIV";
|
||||
this.divName = arguments[0];
|
||||
}
|
||||
else {
|
||||
this.type="WINDOW";
|
||||
}
|
||||
this.use_gebi = false;
|
||||
this.use_css = false;
|
||||
this.use_layers = false;
|
||||
if (document.getElementById) { this.use_gebi = true; }
|
||||
else if (document.all) { this.use_css = true; }
|
||||
else if (document.layers) { this.use_layers = true; }
|
||||
else { this.type = "WINDOW"; }
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
// Method mappings
|
||||
this.getXYPosition = PopupWindow_getXYPosition;
|
||||
this.populate = PopupWindow_populate;
|
||||
this.setUrl = PopupWindow_setUrl;
|
||||
this.setWindowProperties = PopupWindow_setWindowProperties;
|
||||
this.refresh = PopupWindow_refresh;
|
||||
this.showPopup = PopupWindow_showPopup;
|
||||
this.hidePopup = PopupWindow_hidePopup;
|
||||
this.setSize = PopupWindow_setSize;
|
||||
this.isClicked = PopupWindow_isClicked;
|
||||
this.autoHide = PopupWindow_autoHide;
|
||||
this.hideIfNotClicked = PopupWindow_hideIfNotClicked;
|
||||
}
|
||||
|
||||
/* SOURCE FILE: ColorPicker2.js */
|
||||
|
||||
/*
|
||||
Last modified: 02/24/2003
|
||||
|
||||
DESCRIPTION: This widget is used to select a color, in hexadecimal #RRGGBB
|
||||
form. It uses a color "swatch" to display the standard 216-color web-safe
|
||||
palette. The user can then click on a color to select it.
|
||||
|
||||
COMPATABILITY: See notes in AnchorPosition.js and PopupWindow.js.
|
||||
Only the latest DHTML-capable browsers will show the color and hex values
|
||||
at the bottom as your mouse goes over them.
|
||||
|
||||
USAGE:
|
||||
// Create a new ColorPicker object using DHTML popup
|
||||
var cp = new ColorPicker();
|
||||
|
||||
// Create a new ColorPicker object using Window Popup
|
||||
var cp = new ColorPicker('window');
|
||||
|
||||
// Add a link in your page to trigger the popup. For example:
|
||||
<A HREF="#" onClick="cp.show('pick');return false;" NAME="pick" ID="pick">Pick</A>
|
||||
|
||||
// Or use the built-in "select" function to do the dirty work for you:
|
||||
<A HREF="#" onClick="cp.select(document.forms[0].color,'pick');return false;" NAME="pick" ID="pick">Pick</A>
|
||||
|
||||
// If using DHTML popup, write out the required DIV tag near the bottom
|
||||
// of your page.
|
||||
<SCRIPT LANGUAGE="JavaScript">cp.writeDiv()</SCRIPT>
|
||||
|
||||
// Write the 'pickColor' function that will be called when the user clicks
|
||||
// a color and do something with the value. This is only required if you
|
||||
// want to do something other than simply populate a form field, which is
|
||||
// what the 'select' function will give you.
|
||||
function pickColor(color) {
|
||||
field.value = color;
|
||||
}
|
||||
|
||||
NOTES:
|
||||
1) Requires the functions in AnchorPosition.js and PopupWindow.js
|
||||
|
||||
2) Your anchor tag MUST contain both NAME and ID attributes which are the
|
||||
same. For example:
|
||||
<A NAME="test" ID="test"> </A>
|
||||
|
||||
3) There must be at least a space between <A> </A> for IE5.5 to see the
|
||||
anchor tag correctly. Do not do <A></A> with no space.
|
||||
|
||||
4) When a ColorPicker object is created, a handler for 'onmouseup' is
|
||||
attached to any event handler you may have already defined. Do NOT define
|
||||
an event handler for 'onmouseup' after you define a ColorPicker object or
|
||||
the color picker will not hide itself correctly.
|
||||
*/
|
||||
ColorPicker_targetInput = null;
|
||||
function ColorPicker_writeDiv() {
|
||||
document.writeln("<DIV ID=\"colorPickerDiv\" STYLE=\"position:absolute;visibility:hidden;\"> </DIV>");
|
||||
}
|
||||
|
||||
function ColorPicker_show(anchorname) {
|
||||
this.showPopup(anchorname);
|
||||
}
|
||||
|
||||
function ColorPicker_pickColor(color,obj) {
|
||||
obj.hidePopup();
|
||||
pickColor(color);
|
||||
}
|
||||
|
||||
// A Default "pickColor" function to accept the color passed back from popup.
|
||||
// User can over-ride this with their own function.
|
||||
function pickColor(color) {
|
||||
if (ColorPicker_targetInput==null) {
|
||||
alert("Target Input is null, which means you either didn't use the 'select' function or you have no defined your own 'pickColor' function to handle the picked color!");
|
||||
return;
|
||||
}
|
||||
ColorPicker_targetInput.value = color;
|
||||
}
|
||||
|
||||
// This function is the easiest way to popup the window, select a color, and
|
||||
// have the value populate a form field, which is what most people want to do.
|
||||
function ColorPicker_select(inputobj,linkname) {
|
||||
if (inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea") {
|
||||
alert("colorpicker.select: Input object passed is not a valid form input object");
|
||||
window.ColorPicker_targetInput=null;
|
||||
return;
|
||||
}
|
||||
window.ColorPicker_targetInput = inputobj;
|
||||
this.show(linkname);
|
||||
}
|
||||
|
||||
// This function runs when you move your mouse over a color block, if you have a newer browser
|
||||
function ColorPicker_highlightColor(c) {
|
||||
var thedoc = (arguments.length>1)?arguments[1]:window.document;
|
||||
var d = thedoc.getElementById("colorPickerSelectedColor");
|
||||
d.style.backgroundColor = c;
|
||||
d = thedoc.getElementById("colorPickerSelectedColorValue");
|
||||
d.innerHTML = c;
|
||||
}
|
||||
|
||||
function ColorPicker() {
|
||||
var windowMode = false;
|
||||
// Create a new PopupWindow object
|
||||
if (arguments.length==0) {
|
||||
var divname = "colorPickerDiv";
|
||||
}
|
||||
else if (arguments[0] == "window") {
|
||||
var divname = '';
|
||||
windowMode = true;
|
||||
}
|
||||
else {
|
||||
var divname = arguments[0];
|
||||
}
|
||||
|
||||
if (divname != "") {
|
||||
var cp = new PopupWindow(divname);
|
||||
}
|
||||
else {
|
||||
var cp = new PopupWindow();
|
||||
cp.setSize(225,250);
|
||||
}
|
||||
|
||||
// Object variables
|
||||
cp.currentValue = "#FFFFFF";
|
||||
|
||||
// Method Mappings
|
||||
cp.writeDiv = ColorPicker_writeDiv;
|
||||
cp.highlightColor = ColorPicker_highlightColor;
|
||||
cp.show = ColorPicker_show;
|
||||
cp.select = ColorPicker_select;
|
||||
|
||||
// Code to populate color picker window
|
||||
var colors = new Array( "#4180B6","#69AEE7","#000000","#000033","#000066","#000099","#0000CC","#0000FF","#330000","#330033","#330066","#330099",
|
||||
"#3300CC","#3300FF","#660000","#660033","#660066","#660099","#6600CC","#6600FF","#990000","#990033","#990066","#990099",
|
||||
"#9900CC","#9900FF","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#FF0000","#FF0033","#FF0066","#FF0099",
|
||||
"#FF00CC","#FF00FF","#7FFFFF","#7FFFFF","#7FF7F7","#7FEFEF","#7FE7E7","#7FDFDF","#7FD7D7","#7FCFCF","#7FC7C7","#7FBFBF",
|
||||
"#7FB7B7","#7FAFAF","#7FA7A7","#7F9F9F","#7F9797","#7F8F8F","#7F8787","#7F7F7F","#7F7777","#7F6F6F","#7F6767","#7F5F5F",
|
||||
"#7F5757","#7F4F4F","#7F4747","#7F3F3F","#7F3737","#7F2F2F","#7F2727","#7F1F1F","#7F1717","#7F0F0F","#7F0707","#7F0000",
|
||||
|
||||
"#4180B6","#69AEE7","#003300","#003333","#003366","#003399","#0033CC","#0033FF","#333300","#333333","#333366","#333399",
|
||||
"#3333CC","#3333FF","#663300","#663333","#663366","#663399","#6633CC","#6633FF","#993300","#993333","#993366","#993399",
|
||||
"#9933CC","#9933FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#FF3300","#FF3333","#FF3366","#FF3399",
|
||||
"#FF33CC","#FF33FF","#FF7FFF","#FF7FFF","#F77FF7","#EF7FEF","#E77FE7","#DF7FDF","#D77FD7","#CF7FCF","#C77FC7","#BF7FBF",
|
||||
"#B77FB7","#AF7FAF","#A77FA7","#9F7F9F","#977F97","#8F7F8F","#877F87","#7F7F7F","#777F77","#6F7F6F","#677F67","#5F7F5F",
|
||||
"#577F57","#4F7F4F","#477F47","#3F7F3F","#377F37","#2F7F2F","#277F27","#1F7F1F","#177F17","#0F7F0F","#077F07","#007F00",
|
||||
|
||||
"#4180B6","#69AEE7","#006600","#006633","#006666","#006699","#0066CC","#0066FF","#336600","#336633","#336666","#336699",
|
||||
"#3366CC","#3366FF","#666600","#666633","#666666","#666699","#6666CC","#6666FF","#996600","#996633","#996666","#996699",
|
||||
"#9966CC","#9966FF","#CC6600","#CC6633","#CC6666","#CC6699","#CC66CC","#CC66FF","#FF6600","#FF6633","#FF6666","#FF6699",
|
||||
"#FF66CC","#FF66FF","#FFFF7F","#FFFF7F","#F7F77F","#EFEF7F","#E7E77F","#DFDF7F","#D7D77F","#CFCF7F","#C7C77F","#BFBF7F",
|
||||
"#B7B77F","#AFAF7F","#A7A77F","#9F9F7F","#97977F","#8F8F7F","#87877F","#7F7F7F","#77777F","#6F6F7F","#67677F","#5F5F7F",
|
||||
"#57577F","#4F4F7F","#47477F","#3F3F7F","#37377F","#2F2F7F","#27277F","#1F1F7F","#17177F","#0F0F7F","#07077F","#00007F",
|
||||
|
||||
"#4180B6","#69AEE7","#009900","#009933","#009966","#009999","#0099CC","#0099FF","#339900","#339933","#339966","#339999",
|
||||
"#3399CC","#3399FF","#669900","#669933","#669966","#669999","#6699CC","#6699FF","#999900","#999933","#999966","#999999",
|
||||
"#9999CC","#9999FF","#CC9900","#CC9933","#CC9966","#CC9999","#CC99CC","#CC99FF","#FF9900","#FF9933","#FF9966","#FF9999",
|
||||
"#FF99CC","#FF99FF","#3FFFFF","#3FFFFF","#3FF7F7","#3FEFEF","#3FE7E7","#3FDFDF","#3FD7D7","#3FCFCF","#3FC7C7","#3FBFBF",
|
||||
"#3FB7B7","#3FAFAF","#3FA7A7","#3F9F9F","#3F9797","#3F8F8F","#3F8787","#3F7F7F","#3F7777","#3F6F6F","#3F6767","#3F5F5F",
|
||||
"#3F5757","#3F4F4F","#3F4747","#3F3F3F","#3F3737","#3F2F2F","#3F2727","#3F1F1F","#3F1717","#3F0F0F","#3F0707","#3F0000",
|
||||
|
||||
"#4180B6","#69AEE7","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#33CC00","#33CC33","#33CC66","#33CC99",
|
||||
"#33CCCC","#33CCFF","#66CC00","#66CC33","#66CC66","#66CC99","#66CCCC","#66CCFF","#99CC00","#99CC33","#99CC66","#99CC99",
|
||||
"#99CCCC","#99CCFF","#CCCC00","#CCCC33","#CCCC66","#CCCC99","#CCCCCC","#CCCCFF","#FFCC00","#FFCC33","#FFCC66","#FFCC99",
|
||||
"#FFCCCC","#FFCCFF","#FF3FFF","#FF3FFF","#F73FF7","#EF3FEF","#E73FE7","#DF3FDF","#D73FD7","#CF3FCF","#C73FC7","#BF3FBF",
|
||||
"#B73FB7","#AF3FAF","#A73FA7","#9F3F9F","#973F97","#8F3F8F","#873F87","#7F3F7F","#773F77","#6F3F6F","#673F67","#5F3F5F",
|
||||
"#573F57","#4F3F4F","#473F47","#3F3F3F","#373F37","#2F3F2F","#273F27","#1F3F1F","#173F17","#0F3F0F","#073F07","#003F00",
|
||||
|
||||
"#4180B6","#69AEE7","#00FF00","#00FF33","#00FF66","#00FF99","#00FFCC","#00FFFF","#33FF00","#33FF33","#33FF66","#33FF99",
|
||||
"#33FFCC","#33FFFF","#66FF00","#66FF33","#66FF66","#66FF99","#66FFCC","#66FFFF","#99FF00","#99FF33","#99FF66","#99FF99",
|
||||
"#99FFCC","#99FFFF","#CCFF00","#CCFF33","#CCFF66","#CCFF99","#CCFFCC","#CCFFFF","#FFFF00","#FFFF33","#FFFF66","#FFFF99",
|
||||
"#FFFFCC","#FFFFFF","#FFFF3F","#FFFF3F","#F7F73F","#EFEF3F","#E7E73F","#DFDF3F","#D7D73F","#CFCF3F","#C7C73F","#BFBF3F",
|
||||
"#B7B73F","#AFAF3F","#A7A73F","#9F9F3F","#97973F","#8F8F3F","#87873F","#7F7F3F","#77773F","#6F6F3F","#67673F","#5F5F3F",
|
||||
"#57573F","#4F4F3F","#47473F","#3F3F3F","#37373F","#2F2F3F","#27273F","#1F1F3F","#17173F","#0F0F3F","#07073F","#00003F",
|
||||
|
||||
"#4180B6","#69AEE7","#FFFFFF","#FFEEEE","#FFDDDD","#FFCCCC","#FFBBBB","#FFAAAA","#FF9999","#FF8888","#FF7777","#FF6666",
|
||||
"#FF5555","#FF4444","#FF3333","#FF2222","#FF1111","#FF0000","#FF0000","#FF0000","#FF0000","#EE0000","#DD0000","#CC0000",
|
||||
"#BB0000","#AA0000","#990000","#880000","#770000","#660000","#550000","#440000","#330000","#220000","#110000","#000000",
|
||||
"#000000","#000000","#000000","#001111","#002222","#003333","#004444","#005555","#006666","#007777","#008888","#009999",
|
||||
"#00AAAA","#00BBBB","#00CCCC","#00DDDD","#00EEEE","#00FFFF","#00FFFF","#00FFFF","#00FFFF","#11FFFF","#22FFFF","#33FFFF",
|
||||
"#44FFFF","#55FFFF","#66FFFF","#77FFFF","#88FFFF","#99FFFF","#AAFFFF","#BBFFFF","#CCFFFF","#DDFFFF","#EEFFFF","#FFFFFF",
|
||||
|
||||
"#4180B6","#69AEE7","#FFFFFF","#EEFFEE","#DDFFDD","#CCFFCC","#BBFFBB","#AAFFAA","#99FF99","#88FF88","#77FF77","#66FF66",
|
||||
"#55FF55","#44FF44","#33FF33","#22FF22","#11FF11","#00FF00","#00FF00","#00FF00","#00FF00","#00EE00","#00DD00","#00CC00",
|
||||
"#00BB00","#00AA00","#009900","#008800","#007700","#006600","#005500","#004400","#003300","#002200","#001100","#000000",
|
||||
"#000000","#000000","#000000","#110011","#220022","#330033","#440044","#550055","#660066","#770077","#880088","#990099",
|
||||
"#AA00AA","#BB00BB","#CC00CC","#DD00DD","#EE00EE","#FF00FF","#FF00FF","#FF00FF","#FF00FF","#FF11FF","#FF22FF","#FF33FF",
|
||||
"#FF44FF","#FF55FF","#FF66FF","#FF77FF","#FF88FF","#FF99FF","#FFAAFF","#FFBBFF","#FFCCFF","#FFDDFF","#FFEEFF","#FFFFFF",
|
||||
|
||||
"#4180B6","#69AEE7","#FFFFFF","#EEEEFF","#DDDDFF","#CCCCFF","#BBBBFF","#AAAAFF","#9999FF","#8888FF","#7777FF","#6666FF",
|
||||
"#5555FF","#4444FF","#3333FF","#2222FF","#1111FF","#0000FF","#0000FF","#0000FF","#0000FF","#0000EE","#0000DD","#0000CC",
|
||||
"#0000BB","#0000AA","#000099","#000088","#000077","#000066","#000055","#000044","#000033","#000022","#000011","#000000",
|
||||
"#000000","#000000","#000000","#111100","#222200","#333300","#444400","#555500","#666600","#777700","#888800","#999900",
|
||||
"#AAAA00","#BBBB00","#CCCC00","#DDDD00","#EEEE00","#FFFF00","#FFFF00","#FFFF00","#FFFF00","#FFFF11","#FFFF22","#FFFF33",
|
||||
"#FFFF44","#FFFF55","#FFFF66","#FFFF77","#FFFF88","#FFFF99","#FFFFAA","#FFFFBB","#FFFFCC","#FFFFDD","#FFFFEE","#FFFFFF",
|
||||
|
||||
"#4180B6","#69AEE7","#FFFFFF","#FFFFFF","#FBFBFB","#F7F7F7","#F3F3F3","#EFEFEF","#EBEBEB","#E7E7E7","#E3E3E3","#DFDFDF",
|
||||
"#DBDBDB","#D7D7D7","#D3D3D3","#CFCFCF","#CBCBCB","#C7C7C7","#C3C3C3","#BFBFBF","#BBBBBB","#B7B7B7","#B3B3B3","#AFAFAF",
|
||||
"#ABABAB","#A7A7A7","#A3A3A3","#9F9F9F","#9B9B9B","#979797","#939393","#8F8F8F","#8B8B8B","#878787","#838383","#7F7F7F",
|
||||
"#7B7B7B","#777777","#737373","#6F6F6F","#6B6B6B","#676767","#636363","#5F5F5F","#5B5B5B","#575757","#535353","#4F4F4F",
|
||||
"#4B4B4B","#474747","#434343","#3F3F3F","#3B3B3B","#373737","#333333","#2F2F2F","#2B2B2B","#272727","#232323","#1F1F1F",
|
||||
"#1B1B1B","#171717","#131313","#0F0F0F","#0B0B0B","#070707","#030303","#000000","#000000","#000000","#000000","#000000");
|
||||
var total = colors.length;
|
||||
var width = 72;
|
||||
var cp_contents = "";
|
||||
var windowRef = (windowMode)?"window.opener.":"";
|
||||
if (windowMode) {
|
||||
cp_contents += "<html><head><title>Select Color</title></head>";
|
||||
cp_contents += "<body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><span style='text-align: center;'>";
|
||||
}
|
||||
cp_contents += "<table style='border: none;' cellspacing=0 cellpadding=0>";
|
||||
var use_highlight = (document.getElementById || document.all)?true:false;
|
||||
for (var i=0; i<total; i++) {
|
||||
if ((i % width) == 0) { cp_contents += "<tr>"; }
|
||||
if (use_highlight) { var mo = 'onMouseOver="'+windowRef+'ColorPicker_highlightColor(\''+colors[i]+'\',window.document)"'; }
|
||||
else { mo = ""; }
|
||||
cp_contents += '<td style="background-color: '+colors[i]+';"><a href="javascript:void()" onclick="'+windowRef+'ColorPicker_pickColor(\''+colors[i]+'\','+windowRef+'window.popupWindowObjects['+cp.index+']);return false;" '+mo+'> </a></td>';
|
||||
if ( ((i+1)>=total) || (((i+1) % width) == 0)) {
|
||||
cp_contents += "</tr>";
|
||||
}
|
||||
}
|
||||
// If the browser supports dynamically changing TD cells, add the fancy stuff
|
||||
if (document.getElementById) {
|
||||
var width1 = Math.floor(width/2);
|
||||
var width2 = width = width1;
|
||||
cp_contents += "<tr><td colspan='"+width1+"' style='background-color: #FFF;' ID='colorPickerSelectedColor'> </td><td colspan='"+width2+"' style='text-align: center;' id='colorPickerSelectedColorValue'>#FFFFFF</td></tr>";
|
||||
}
|
||||
cp_contents += "</table>";
|
||||
if (windowMode) {
|
||||
cp_contents += "</span></body></html>";
|
||||
}
|
||||
// end populate code
|
||||
|
||||
// Write the contents to the popup object
|
||||
cp.populate(cp_contents+"\n");
|
||||
// Move the table down a bit so you can see it
|
||||
cp.offsetY = 25;
|
||||
cp.autoHide();
|
||||
return cp;
|
||||
}
|
||||
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,444 @@
|
||||
/**
|
||||
* Handles the addition of the comment form.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @output wp-includes/js/comment-reply.js
|
||||
*
|
||||
* @namespace addComment
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
window.addComment = ( function( window ) {
|
||||
// Avoid scope lookups on commonly used variables.
|
||||
var document = window.document;
|
||||
|
||||
// Settings.
|
||||
var config = {
|
||||
commentReplyClass : 'comment-reply-link',
|
||||
commentReplyTitleId : 'reply-title',
|
||||
cancelReplyId : 'cancel-comment-reply-link',
|
||||
commentFormId : 'commentform',
|
||||
temporaryFormId : 'wp-temp-form-div',
|
||||
parentIdFieldId : 'comment_parent',
|
||||
postIdFieldId : 'comment_post_ID'
|
||||
};
|
||||
|
||||
// Cross browser MutationObserver.
|
||||
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
|
||||
|
||||
// Check browser cuts the mustard.
|
||||
var cutsTheMustard = 'querySelector' in document && 'addEventListener' in window;
|
||||
|
||||
/*
|
||||
* Check browser supports dataset.
|
||||
* !! sets the variable to true if the property exists.
|
||||
*/
|
||||
var supportsDataset = !! document.documentElement.dataset;
|
||||
|
||||
// For holding the cancel element.
|
||||
var cancelElement;
|
||||
|
||||
// For holding the comment form element.
|
||||
var commentFormElement;
|
||||
|
||||
// The respond element.
|
||||
var respondElement;
|
||||
|
||||
// The mutation observer.
|
||||
var observer;
|
||||
|
||||
if ( cutsTheMustard && document.readyState !== 'loading' ) {
|
||||
ready();
|
||||
} else if ( cutsTheMustard ) {
|
||||
window.addEventListener( 'DOMContentLoaded', ready, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up object variables after the DOM is ready.
|
||||
*
|
||||
* @since 5.1.1
|
||||
*/
|
||||
function ready() {
|
||||
// Initialize the events.
|
||||
init();
|
||||
|
||||
// Set up a MutationObserver to check for comments loaded late.
|
||||
observeChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add events to links classed .comment-reply-link.
|
||||
*
|
||||
* Searches the context for reply links and adds the JavaScript events
|
||||
* required to move the comment form. To allow for lazy loading of
|
||||
* comments this method is exposed as window.commentReply.init().
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @memberOf addComment
|
||||
*
|
||||
* @param {HTMLElement} context The parent DOM element to search for links.
|
||||
*/
|
||||
function init( context ) {
|
||||
if ( ! cutsTheMustard ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get required elements.
|
||||
cancelElement = getElementById( config.cancelReplyId );
|
||||
commentFormElement = getElementById( config.commentFormId );
|
||||
|
||||
// No cancel element, no replies.
|
||||
if ( ! cancelElement ) {
|
||||
return;
|
||||
}
|
||||
|
||||
cancelElement.addEventListener( 'touchstart', cancelEvent );
|
||||
cancelElement.addEventListener( 'click', cancelEvent );
|
||||
|
||||
// Submit the comment form when the user types [Ctrl] or [Cmd] + [Enter].
|
||||
var submitFormHandler = function( e ) {
|
||||
if ( ( e.metaKey || e.ctrlKey ) && e.keyCode === 13 ) {
|
||||
commentFormElement.removeEventListener( 'keydown', submitFormHandler );
|
||||
e.preventDefault();
|
||||
// The submit button ID is 'submit' so we can't call commentFormElement.submit(). Click it instead.
|
||||
commentFormElement.submit.click();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if ( commentFormElement ) {
|
||||
commentFormElement.addEventListener( 'keydown', submitFormHandler );
|
||||
}
|
||||
|
||||
var links = replyLinks( context );
|
||||
var element;
|
||||
|
||||
for ( var i = 0, l = links.length; i < l; i++ ) {
|
||||
element = links[i];
|
||||
|
||||
element.addEventListener( 'touchstart', clickEvent );
|
||||
element.addEventListener( 'click', clickEvent );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all links classed .comment-reply-link.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {HTMLElement} context The parent DOM element to search for links.
|
||||
*
|
||||
* @return {HTMLCollection|NodeList|Array}
|
||||
*/
|
||||
function replyLinks( context ) {
|
||||
var selectorClass = config.commentReplyClass;
|
||||
var allReplyLinks;
|
||||
|
||||
// childNodes is a handy check to ensure the context is a HTMLElement.
|
||||
if ( ! context || ! context.childNodes ) {
|
||||
context = document;
|
||||
}
|
||||
|
||||
if ( document.getElementsByClassName ) {
|
||||
// Fastest.
|
||||
allReplyLinks = context.getElementsByClassName( selectorClass );
|
||||
}
|
||||
else {
|
||||
// Fast.
|
||||
allReplyLinks = context.querySelectorAll( '.' + selectorClass );
|
||||
}
|
||||
|
||||
return allReplyLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel event handler.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {Event} event The calling event.
|
||||
*/
|
||||
function cancelEvent( event ) {
|
||||
var cancelLink = this;
|
||||
var temporaryFormId = config.temporaryFormId;
|
||||
var temporaryElement = getElementById( temporaryFormId );
|
||||
|
||||
if ( ! temporaryElement || ! respondElement ) {
|
||||
// Conditions for cancel link fail.
|
||||
return;
|
||||
}
|
||||
|
||||
getElementById( config.parentIdFieldId ).value = '0';
|
||||
|
||||
// Move the respond form back in place of the temporary element.
|
||||
var headingText = temporaryElement.textContent;
|
||||
temporaryElement.parentNode.replaceChild( respondElement, temporaryElement );
|
||||
cancelLink.style.display = 'none';
|
||||
|
||||
var replyHeadingElement = getElementById( config.commentReplyTitleId );
|
||||
var replyHeadingTextNode = replyHeadingElement && replyHeadingElement.firstChild;
|
||||
var replyLinkToParent = replyHeadingTextNode && replyHeadingTextNode.nextSibling;
|
||||
|
||||
if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE && headingText ) {
|
||||
if ( replyLinkToParent && 'A' === replyLinkToParent.nodeName && replyLinkToParent.id !== config.cancelReplyId ) {
|
||||
replyLinkToParent.style.display = '';
|
||||
}
|
||||
|
||||
replyHeadingTextNode.textContent = headingText;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Click event handler.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {Event} event The calling event.
|
||||
*/
|
||||
function clickEvent( event ) {
|
||||
var replyNode = getElementById( config.commentReplyTitleId );
|
||||
var defaultReplyHeading = replyNode && replyNode.firstChild.textContent;
|
||||
var replyLink = this,
|
||||
commId = getDataAttribute( replyLink, 'belowelement' ),
|
||||
parentId = getDataAttribute( replyLink, 'commentid' ),
|
||||
respondId = getDataAttribute( replyLink, 'respondelement' ),
|
||||
postId = getDataAttribute( replyLink, 'postid' ),
|
||||
replyTo = getDataAttribute( replyLink, 'replyto' ) || defaultReplyHeading,
|
||||
follow;
|
||||
|
||||
if ( ! commId || ! parentId || ! respondId || ! postId ) {
|
||||
/*
|
||||
* Theme or plugin defines own link via custom `wp_list_comments()` callback
|
||||
* and calls `moveForm()` either directly or via a custom event hook.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Third party comments systems can hook into this function via the global scope,
|
||||
* therefore the click event needs to reference the global scope.
|
||||
*/
|
||||
follow = window.addComment.moveForm( commId, parentId, respondId, postId, replyTo );
|
||||
if ( false === follow ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mutation observer to check for newly inserted comments.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*/
|
||||
function observeChanges() {
|
||||
if ( ! MutationObserver ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var observerOptions = {
|
||||
childList: true,
|
||||
subtree: true
|
||||
};
|
||||
|
||||
observer = new MutationObserver( handleChanges );
|
||||
observer.observe( document.body, observerOptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles DOM changes, calling init() if any new nodes are added.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {Array} mutationRecords Array of MutationRecord objects.
|
||||
*/
|
||||
function handleChanges( mutationRecords ) {
|
||||
var i = mutationRecords.length;
|
||||
|
||||
while ( i-- ) {
|
||||
// Call init() once if any record in this set adds nodes.
|
||||
if ( mutationRecords[ i ].addedNodes.length ) {
|
||||
init();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Backward compatible getter of data-* attribute.
|
||||
*
|
||||
* Uses element.dataset if it exists, otherwise uses getAttribute.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {HTMLElement} Element DOM element with the attribute.
|
||||
* @param {string} Attribute the attribute to get.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
function getDataAttribute( element, attribute ) {
|
||||
if ( supportsDataset ) {
|
||||
return element.dataset[attribute];
|
||||
}
|
||||
else {
|
||||
return element.getAttribute( 'data-' + attribute );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get element by ID.
|
||||
*
|
||||
* Local alias for document.getElementById.
|
||||
*
|
||||
* @since 5.1.0
|
||||
*
|
||||
* @param {HTMLElement} The requested element.
|
||||
*/
|
||||
function getElementById( elementId ) {
|
||||
return document.getElementById( elementId );
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the reply form from its current position to the reply location.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @memberOf addComment
|
||||
*
|
||||
* @param {string} addBelowId HTML ID of element the form follows.
|
||||
* @param {string} commentId Database ID of comment being replied to.
|
||||
* @param {string} respondId HTML ID of 'respond' element.
|
||||
* @param {string} postId Database ID of the post.
|
||||
* @param {string} replyTo Form heading content.
|
||||
*/
|
||||
function moveForm( addBelowId, commentId, respondId, postId, replyTo ) {
|
||||
// Get elements based on their IDs.
|
||||
var addBelowElement = getElementById( addBelowId );
|
||||
respondElement = getElementById( respondId );
|
||||
|
||||
// Get the hidden fields.
|
||||
var parentIdField = getElementById( config.parentIdFieldId );
|
||||
var postIdField = getElementById( config.postIdFieldId );
|
||||
var element, cssHidden, style;
|
||||
|
||||
var replyHeading = getElementById( config.commentReplyTitleId );
|
||||
var replyHeadingTextNode = replyHeading && replyHeading.firstChild;
|
||||
var replyLinkToParent = replyHeadingTextNode && replyHeadingTextNode.nextSibling;
|
||||
|
||||
if ( ! addBelowElement || ! respondElement || ! parentIdField ) {
|
||||
// Missing key elements, fail.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'undefined' === typeof replyTo ) {
|
||||
replyTo = replyHeadingTextNode && replyHeadingTextNode.textContent;
|
||||
}
|
||||
|
||||
addPlaceHolder( respondElement );
|
||||
|
||||
// Set the value of the post.
|
||||
if ( postId && postIdField ) {
|
||||
postIdField.value = postId;
|
||||
}
|
||||
|
||||
parentIdField.value = commentId;
|
||||
|
||||
cancelElement.style.display = '';
|
||||
addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling );
|
||||
|
||||
if ( replyHeadingTextNode && replyHeadingTextNode.nodeType === Node.TEXT_NODE ) {
|
||||
if ( replyLinkToParent && 'A' === replyLinkToParent.nodeName && replyLinkToParent.id !== config.cancelReplyId ) {
|
||||
replyLinkToParent.style.display = 'none';
|
||||
}
|
||||
|
||||
replyHeadingTextNode.textContent = replyTo;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for backward compatibility with third party commenting systems
|
||||
* hooking into the event using older techniques.
|
||||
*/
|
||||
cancelElement.onclick = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Focus on the first field in the comment form.
|
||||
try {
|
||||
for ( var i = 0; i < commentFormElement.elements.length; i++ ) {
|
||||
element = commentFormElement.elements[i];
|
||||
cssHidden = false;
|
||||
|
||||
// Get elements computed style.
|
||||
if ( 'getComputedStyle' in window ) {
|
||||
// Modern browsers.
|
||||
style = window.getComputedStyle( element );
|
||||
} else if ( document.documentElement.currentStyle ) {
|
||||
// IE 8.
|
||||
style = element.currentStyle;
|
||||
}
|
||||
|
||||
/*
|
||||
* For display none, do the same thing jQuery does. For visibility,
|
||||
* check the element computed style since browsers are already doing
|
||||
* the job for us. In fact, the visibility computed style is the actual
|
||||
* computed value and already takes into account the element ancestors.
|
||||
*/
|
||||
if ( ( element.offsetWidth <= 0 && element.offsetHeight <= 0 ) || style.visibility === 'hidden' ) {
|
||||
cssHidden = true;
|
||||
}
|
||||
|
||||
// Skip form elements that are hidden or disabled.
|
||||
if ( 'hidden' === element.type || element.disabled || cssHidden ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
element.focus();
|
||||
// Stop after the first focusable element.
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* false is returned for backward compatibility with third party commenting systems
|
||||
* hooking into this function.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add placeholder element.
|
||||
*
|
||||
* Places a place holder element above the #respond element for
|
||||
* the form to be returned to if needs be.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param {HTMLelement} respondElement the #respond element holding comment form.
|
||||
*/
|
||||
function addPlaceHolder( respondElement ) {
|
||||
var temporaryFormId = config.temporaryFormId;
|
||||
var temporaryElement = getElementById( temporaryFormId );
|
||||
var replyElement = getElementById( config.commentReplyTitleId );
|
||||
var initialHeadingText = replyElement ? replyElement.firstChild.textContent : '';
|
||||
|
||||
if ( temporaryElement ) {
|
||||
// The element already exists, no need to recreate.
|
||||
return;
|
||||
}
|
||||
|
||||
temporaryElement = document.createElement( 'div' );
|
||||
temporaryElement.id = temporaryFormId;
|
||||
temporaryElement.style.display = 'none';
|
||||
temporaryElement.textContent = initialHeadingText;
|
||||
respondElement.parentNode.insertBefore( temporaryElement, respondElement );
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
moveForm: moveForm
|
||||
};
|
||||
})( window );
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
window.addComment=function(v){var I,C,h,E=v.document,b={commentReplyClass:"comment-reply-link",commentReplyTitleId:"reply-title",cancelReplyId:"cancel-comment-reply-link",commentFormId:"commentform",temporaryFormId:"wp-temp-form-div",parentIdFieldId:"comment_parent",postIdFieldId:"comment_post_ID"},e=v.MutationObserver||v.WebKitMutationObserver||v.MozMutationObserver,r="querySelector"in E&&"addEventListener"in v,n=!!E.documentElement.dataset;function t(){d(),e&&new e(o).observe(E.body,{childList:!0,subtree:!0})}function d(e){if(r&&(I=g(b.cancelReplyId),C=g(b.commentFormId),I)){I.addEventListener("touchstart",l),I.addEventListener("click",l);function t(e){if((e.metaKey||e.ctrlKey)&&13===e.keyCode)return C.removeEventListener("keydown",t),e.preventDefault(),C.submit.click(),!1}C&&C.addEventListener("keydown",t);for(var n,d=function(e){var t=b.commentReplyClass;e&&e.childNodes||(e=E);e=E.getElementsByClassName?e.getElementsByClassName(t):e.querySelectorAll("."+t);return e}(e),o=0,i=d.length;o<i;o++)(n=d[o]).addEventListener("touchstart",a),n.addEventListener("click",a)}}function l(e){var t,n,d=g(b.temporaryFormId);d&&h&&(g(b.parentIdFieldId).value="0",t=d.textContent,d.parentNode.replaceChild(h,d),this.style.display="none",n=(d=(d=g(b.commentReplyTitleId))&&d.firstChild)&&d.nextSibling,d&&d.nodeType===Node.TEXT_NODE&&t&&(n&&"A"===n.nodeName&&n.id!==b.cancelReplyId&&(n.style.display=""),d.textContent=t),e.preventDefault())}function a(e){var t=g(b.commentReplyTitleId),t=t&&t.firstChild.textContent,n=this,d=m(n,"belowelement"),o=m(n,"commentid"),i=m(n,"respondelement"),r=m(n,"postid"),n=m(n,"replyto")||t;d&&o&&i&&r&&!1===v.addComment.moveForm(d,o,i,r,n)&&e.preventDefault()}function o(e){for(var t=e.length;t--;)if(e[t].addedNodes.length)return void d()}function m(e,t){return n?e.dataset[t]:e.getAttribute("data-"+t)}function g(e){return E.getElementById(e)}return r&&"loading"!==E.readyState?t():r&&v.addEventListener("DOMContentLoaded",t,!1),{init:d,moveForm:function(e,t,n,d,o){var i,r,l,a,m,c,s,e=g(e),n=(h=g(n),g(b.parentIdFieldId)),y=g(b.postIdFieldId),p=g(b.commentReplyTitleId),u=(p=p&&p.firstChild)&&p.nextSibling;if(e&&h&&n){void 0===o&&(o=p&&p.textContent),a=h,m=b.temporaryFormId,c=g(m),s=(s=g(b.commentReplyTitleId))?s.firstChild.textContent:"",c||((c=E.createElement("div")).id=m,c.style.display="none",c.textContent=s,a.parentNode.insertBefore(c,a)),d&&y&&(y.value=d),n.value=t,I.style.display="",e.parentNode.insertBefore(h,e.nextSibling),p&&p.nodeType===Node.TEXT_NODE&&(u&&"A"===u.nodeName&&u.id!==b.cancelReplyId&&(u.style.display="none"),p.textContent=o),I.onclick=function(){return!1};try{for(var f=0;f<C.elements.length;f++)if(i=C.elements[f],r=!1,"getComputedStyle"in v?l=v.getComputedStyle(i):E.documentElement.currentStyle&&(l=i.currentStyle),(i.offsetWidth<=0&&i.offsetHeight<=0||"hidden"===l.visibility)&&(r=!0),"hidden"!==i.type&&!i.disabled&&!r){i.focus();break}}catch(e){}return!1}}}}(window);
|
||||
@@ -0,0 +1,165 @@
|
||||
.imgCrop_wrap {
|
||||
/* width: 500px; @done_in_js */
|
||||
/* height: 375px; @done_in_js */
|
||||
position: relative;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
/* an extra classname is applied for Opera < 9.0 to fix its lack of opacity support */
|
||||
.imgCrop_wrap.opera8 .imgCrop_overlay,
|
||||
.imgCrop_wrap.opera8 .imgCrop_clickArea {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* fix for IE displaying all boxes at line-height by default, although they are still 1 pixel high until we combine them with the pointless span */
|
||||
.imgCrop_wrap,
|
||||
.imgCrop_wrap * {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.imgCrop_overlay {
|
||||
background-color: #000;
|
||||
opacity: 0.5;
|
||||
filter:alpha(opacity=50);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.imgCrop_selArea {
|
||||
position: absolute;
|
||||
/* @done_in_js
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: transparent url(castle.jpg) no-repeat -210px -110px;
|
||||
*/
|
||||
cursor: move;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* clickArea is all a fix for IE 5.5 & 6 to allow the user to click on the given area */
|
||||
.imgCrop_clickArea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #FFF;
|
||||
opacity: 0.01;
|
||||
filter:alpha(opacity=01);
|
||||
}
|
||||
|
||||
.imgCrop_marqueeHoriz {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: transparent url(marqueeHoriz.gif) repeat-x 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.imgCrop_marqueeVert {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
background: transparent url(marqueeVert.gif) repeat-y 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.imgCrop_marqueeNorth { top: 0; left: 0; }
|
||||
.imgCrop_marqueeEast { top: 0; right: 0; }
|
||||
.imgCrop_marqueeSouth { bottom: 0px; left: 0; }
|
||||
.imgCrop_marqueeWest { top: 0; left: 0; }
|
||||
|
||||
|
||||
.imgCrop_handle {
|
||||
position: absolute;
|
||||
border: 1px solid #333;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #FFF;
|
||||
opacity: 0.5;
|
||||
filter:alpha(opacity=50);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* fix IE 5 box model */
|
||||
* html .imgCrop_handle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
wid\th: 6px;
|
||||
hei\ght: 6px;
|
||||
}
|
||||
|
||||
.imgCrop_handleN {
|
||||
top: -3px;
|
||||
left: 0;
|
||||
/* margin-left: 49%; @done_in_js */
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleNE {
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
cursor: ne-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleE {
|
||||
top: 0;
|
||||
right: -3px;
|
||||
/* margin-top: 49%; @done_in_js */
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleSE {
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleS {
|
||||
right: 0;
|
||||
bottom: -3px;
|
||||
/* margin-right: 49%; @done_in_js */
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleSW {
|
||||
left: -3px;
|
||||
bottom: -3px;
|
||||
cursor: sw-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleW {
|
||||
top: 0;
|
||||
left: -3px;
|
||||
/* margin-top: 49%; @done_in_js */
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleNW {
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
cursor: nw-resize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an area to click & drag around on as the default browser behaviour is to let you drag the image
|
||||
*/
|
||||
.imgCrop_dragArea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 200;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.imgCrop_previewWrap {
|
||||
/* width: 200px; @done_in_js */
|
||||
/* height: 200px; @done_in_js */
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.imgCrop_previewWrap img {
|
||||
position: absolute;
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
/**
|
||||
* Copyright (c) 2006, David Spurr (http://www.defusion.org.uk/)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the David Spurr nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* See scriptaculous.js for full scriptaculous licence
|
||||
*/
|
||||
|
||||
var CropDraggable=Class.create();
|
||||
Object.extend(Object.extend(CropDraggable.prototype,Draggable.prototype),{initialize:function(_1){
|
||||
this.options=Object.extend({drawMethod:function(){
|
||||
}},arguments[1]||{});
|
||||
this.element=$(_1);
|
||||
this.handle=this.element;
|
||||
this.delta=this.currentDelta();
|
||||
this.dragging=false;
|
||||
this.eventMouseDown=this.initDrag.bindAsEventListener(this);
|
||||
Event.observe(this.handle,"mousedown",this.eventMouseDown);
|
||||
Draggables.register(this);
|
||||
},draw:function(_2){
|
||||
var _3=Position.cumulativeOffset(this.element);
|
||||
var d=this.currentDelta();
|
||||
_3[0]-=d[0];
|
||||
_3[1]-=d[1];
|
||||
var p=[0,1].map(function(i){
|
||||
return (_2[i]-_3[i]-this.offset[i]);
|
||||
}.bind(this));
|
||||
this.options.drawMethod(p);
|
||||
}});
|
||||
var Cropper={};
|
||||
Cropper.Img=Class.create();
|
||||
Cropper.Img.prototype={initialize:function(_7,_8){
|
||||
this.options=Object.extend({ratioDim:{x:0,y:0},minWidth:0,minHeight:0,displayOnInit:false,onEndCrop:Prototype.emptyFunction,captureKeys:true},_8||{});
|
||||
if(this.options.minWidth>0&&this.options.minHeight>0){
|
||||
this.options.ratioDim.x=this.options.minWidth;
|
||||
this.options.ratioDim.y=this.options.minHeight;
|
||||
}
|
||||
this.img=$(_7);
|
||||
this.clickCoords={x:0,y:0};
|
||||
this.dragging=false;
|
||||
this.resizing=false;
|
||||
this.isWebKit=/Konqueror|Safari|KHTML/.test(navigator.userAgent);
|
||||
this.isIE=/MSIE/.test(navigator.userAgent);
|
||||
this.isOpera8=/Opera\s[1-8]/.test(navigator.userAgent);
|
||||
this.ratioX=0;
|
||||
this.ratioY=0;
|
||||
this.attached=false;
|
||||
$A(document.getElementsByTagName("script")).each(function(s){
|
||||
if(s.src.match(/cropper\.js/)){
|
||||
var _a=s.src.replace(/cropper\.js(.*)?/,"");
|
||||
var _b=document.createElement("link");
|
||||
_b.rel="stylesheet";
|
||||
_b.type="text/css";
|
||||
_b.href=_a+"cropper.css";
|
||||
_b.media="screen";
|
||||
document.getElementsByTagName("head")[0].appendChild(_b);
|
||||
}
|
||||
});
|
||||
if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
|
||||
var _c=this.getGCD(this.options.ratioDim.x,this.options.ratioDim.y);
|
||||
this.ratioX=this.options.ratioDim.x/_c;
|
||||
this.ratioY=this.options.ratioDim.y/_c;
|
||||
}
|
||||
this.subInitialize();
|
||||
if(this.img.complete||this.isWebKit){
|
||||
this.onLoad();
|
||||
}else{
|
||||
Event.observe(this.img,"load",this.onLoad.bindAsEventListener(this));
|
||||
}
|
||||
},getGCD:function(a,b){return 1;
|
||||
if(b==0){
|
||||
return a;
|
||||
}
|
||||
return this.getGCD(b,a%b);
|
||||
},onLoad:function(){
|
||||
var _f="imgCrop_";
|
||||
var _10=this.img.parentNode;
|
||||
var _11="";
|
||||
if(this.isOpera8){
|
||||
_11=" opera8";
|
||||
}
|
||||
this.imgWrap=Builder.node("div",{"class":_f+"wrap"+_11});
|
||||
if(this.isIE){
|
||||
this.north=Builder.node("div",{"class":_f+"overlay "+_f+"north"},[Builder.node("span")]);
|
||||
this.east=Builder.node("div",{"class":_f+"overlay "+_f+"east"},[Builder.node("span")]);
|
||||
this.south=Builder.node("div",{"class":_f+"overlay "+_f+"south"},[Builder.node("span")]);
|
||||
this.west=Builder.node("div",{"class":_f+"overlay "+_f+"west"},[Builder.node("span")]);
|
||||
var _12=[this.north,this.east,this.south,this.west];
|
||||
}else{
|
||||
this.overlay=Builder.node("div",{"class":_f+"overlay"});
|
||||
var _12=[this.overlay];
|
||||
}
|
||||
this.dragArea=Builder.node("div",{"class":_f+"dragArea"},_12);
|
||||
this.handleN=Builder.node("div",{"class":_f+"handle "+_f+"handleN"});
|
||||
this.handleNE=Builder.node("div",{"class":_f+"handle "+_f+"handleNE"});
|
||||
this.handleE=Builder.node("div",{"class":_f+"handle "+_f+"handleE"});
|
||||
this.handleSE=Builder.node("div",{"class":_f+"handle "+_f+"handleSE"});
|
||||
this.handleS=Builder.node("div",{"class":_f+"handle "+_f+"handleS"});
|
||||
this.handleSW=Builder.node("div",{"class":_f+"handle "+_f+"handleSW"});
|
||||
this.handleW=Builder.node("div",{"class":_f+"handle "+_f+"handleW"});
|
||||
this.handleNW=Builder.node("div",{"class":_f+"handle "+_f+"handleNW"});
|
||||
this.selArea=Builder.node("div",{"class":_f+"selArea"},[Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeNorth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeEast"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeSouth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeWest"},[Builder.node("span")]),this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW,Builder.node("div",{"class":_f+"clickArea"})]);
|
||||
Element.setStyle($(this.selArea),{backgroundColor:"transparent",backgroundRepeat:"no-repeat",backgroundPosition:"0 0"});
|
||||
this.imgWrap.appendChild(this.img);
|
||||
this.imgWrap.appendChild(this.dragArea);
|
||||
this.dragArea.appendChild(this.selArea);
|
||||
this.dragArea.appendChild(Builder.node("div",{"class":_f+"clickArea"}));
|
||||
_10.appendChild(this.imgWrap);
|
||||
Event.observe(this.dragArea,"mousedown",this.startDrag.bindAsEventListener(this));
|
||||
Event.observe(document,"mousemove",this.onDrag.bindAsEventListener(this));
|
||||
Event.observe(document,"mouseup",this.endCrop.bindAsEventListener(this));
|
||||
var _13=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
|
||||
for(var i=0;i<_13.length;i++){
|
||||
Event.observe(_13[i],"mousedown",this.startResize.bindAsEventListener(this));
|
||||
}
|
||||
if(this.options.captureKeys){
|
||||
Event.observe(document,"keydown",this.handleKeys.bindAsEventListener(this));
|
||||
}
|
||||
new CropDraggable(this.selArea,{drawMethod:this.moveArea.bindAsEventListener(this)});
|
||||
this.setParams();
|
||||
},setParams:function(){
|
||||
this.imgW=this.img.width;
|
||||
this.imgH=this.img.height;
|
||||
if(!this.isIE){
|
||||
Element.setStyle($(this.overlay),{width:this.imgW+"px",height:this.imgH+"px"});
|
||||
Element.hide($(this.overlay));
|
||||
Element.setStyle($(this.selArea),{backgroundImage:"url("+this.img.src+")"});
|
||||
}else{
|
||||
Element.setStyle($(this.north),{height:0});
|
||||
Element.setStyle($(this.east),{width:0,height:0});
|
||||
Element.setStyle($(this.south),{height:0});
|
||||
Element.setStyle($(this.west),{width:0,height:0});
|
||||
}
|
||||
Element.setStyle($(this.imgWrap),{"width":this.imgW+"px","height":this.imgH+"px"});
|
||||
Element.hide($(this.selArea));
|
||||
var _15=Position.positionedOffset(this.imgWrap);
|
||||
this.wrapOffsets={"top":_15[1],"left":_15[0]};
|
||||
var _16={x1:0,y1:0,x2:0,y2:0};
|
||||
this.setAreaCoords(_16);
|
||||
if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0&&this.options.displayOnInit){
|
||||
_16.x1=Math.ceil((this.imgW-this.options.ratioDim.x)/2);
|
||||
_16.y1=Math.ceil((this.imgH-this.options.ratioDim.y)/2);
|
||||
_16.x2=_16.x1+this.options.ratioDim.x;
|
||||
_16.y2=_16.y1+this.options.ratioDim.y;
|
||||
Element.show(this.selArea);
|
||||
this.drawArea();
|
||||
this.endCrop();
|
||||
}
|
||||
this.attached=true;
|
||||
},remove:function(){
|
||||
this.attached=false;
|
||||
this.imgWrap.parentNode.insertBefore(this.img,this.imgWrap);
|
||||
this.imgWrap.parentNode.removeChild(this.imgWrap);
|
||||
Event.stopObserving(this.dragArea,"mousedown",this.startDrag.bindAsEventListener(this));
|
||||
Event.stopObserving(document,"mousemove",this.onDrag.bindAsEventListener(this));
|
||||
Event.stopObserving(document,"mouseup",this.endCrop.bindAsEventListener(this));
|
||||
var _17=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
|
||||
for(var i=0;i<_17.length;i++){
|
||||
Event.stopObserving(_17[i],"mousedown",this.startResize.bindAsEventListener(this));
|
||||
}
|
||||
if(this.options.captureKeys){
|
||||
Event.stopObserving(document,"keydown",this.handleKeys.bindAsEventListener(this));
|
||||
}
|
||||
},reset:function(){
|
||||
if(!this.attached){
|
||||
this.onLoad();
|
||||
}else{
|
||||
this.setParams();
|
||||
}
|
||||
this.endCrop();
|
||||
},handleKeys:function(e){
|
||||
var dir={x:0,y:0};
|
||||
if(!this.dragging){
|
||||
switch(e.keyCode){
|
||||
case (37):
|
||||
dir.x=-1;
|
||||
break;
|
||||
case (38):
|
||||
dir.y=-1;
|
||||
break;
|
||||
case (39):
|
||||
dir.x=1;
|
||||
break;
|
||||
case (40):
|
||||
dir.y=1;
|
||||
break;
|
||||
}
|
||||
if(dir.x!=0||dir.y!=0){
|
||||
if(e.shiftKey){
|
||||
dir.x*=10;
|
||||
dir.y*=10;
|
||||
}
|
||||
this.moveArea([this.areaCoords.x1+dir.x,this.areaCoords.y1+dir.y]);
|
||||
Event.stop(e);
|
||||
}
|
||||
}
|
||||
},calcW:function(){
|
||||
return (this.areaCoords.x2-this.areaCoords.x1);
|
||||
},calcH:function(){
|
||||
return (this.areaCoords.y2-this.areaCoords.y1);
|
||||
},moveArea:function(_1b){
|
||||
this.setAreaCoords({x1:_1b[0],y1:_1b[1],x2:_1b[0]+this.calcW(),y2:_1b[1]+this.calcH()},true);
|
||||
this.drawArea();
|
||||
},cloneCoords:function(_1c){
|
||||
return {x1:_1c.x1,y1:_1c.y1,x2:_1c.x2,y2:_1c.y2};
|
||||
},setAreaCoords:function(_1d,_1e,_1f,_20,_21){
|
||||
var _22=typeof _1e!="undefined"?_1e:false;
|
||||
var _23=typeof _1f!="undefined"?_1f:false;
|
||||
if(_1e){
|
||||
var _24=_1d.x2-_1d.x1;
|
||||
var _25=_1d.y2-_1d.y1;
|
||||
if(_1d.x1<0){
|
||||
_1d.x1=0;
|
||||
_1d.x2=_24;
|
||||
}
|
||||
if(_1d.y1<0){
|
||||
_1d.y1=0;
|
||||
_1d.y2=_25;
|
||||
}
|
||||
if(_1d.x2>this.imgW){
|
||||
_1d.x2=this.imgW;
|
||||
_1d.x1=this.imgW-_24;
|
||||
}
|
||||
if(_1d.y2>this.imgH){
|
||||
_1d.y2=this.imgH;
|
||||
_1d.y1=this.imgH-_25;
|
||||
}
|
||||
}else{
|
||||
if(_1d.x1<0){
|
||||
_1d.x1=0;
|
||||
}
|
||||
if(_1d.y1<0){
|
||||
_1d.y1=0;
|
||||
}
|
||||
if(_1d.x2>this.imgW){
|
||||
_1d.x2=this.imgW;
|
||||
}
|
||||
if(_1d.y2>this.imgH){
|
||||
_1d.y2=this.imgH;
|
||||
}
|
||||
if(typeof (_20)!="undefined"){
|
||||
if(this.ratioX>0){
|
||||
this.applyRatio(_1d,{x:this.ratioX,y:this.ratioY},_20,_21);
|
||||
}else{
|
||||
if(_23){
|
||||
this.applyRatio(_1d,{x:1,y:1},_20,_21);
|
||||
}
|
||||
}
|
||||
var _26={a1:_1d.x1,a2:_1d.x2};
|
||||
var _27={a1:_1d.y1,a2:_1d.y2};
|
||||
var _28=this.options.minWidth;
|
||||
var _29=this.options.minHeight;
|
||||
if((_28==0||_29==0)&&_23){
|
||||
if(_28>0){
|
||||
_29=_28;
|
||||
}else{
|
||||
if(_29>0){
|
||||
_28=_29;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.applyMinDimension(_26,_28,_20.x,{min:0,max:this.imgW});
|
||||
this.applyMinDimension(_27,_29,_20.y,{min:0,max:this.imgH});
|
||||
_1d={x1:_26.a1,y1:_27.a1,x2:_26.a2,y2:_27.a2};
|
||||
}
|
||||
}
|
||||
this.areaCoords=_1d;
|
||||
},applyMinDimension:function(_2a,_2b,_2c,_2d){
|
||||
if((_2a.a2-_2a.a1)<_2b){
|
||||
if(_2c==1){
|
||||
_2a.a2=_2a.a1+_2b;
|
||||
}else{
|
||||
_2a.a1=_2a.a2-_2b;
|
||||
}
|
||||
if(_2a.a1<_2d.min){
|
||||
_2a.a1=_2d.min;
|
||||
_2a.a2=_2b;
|
||||
}else{
|
||||
if(_2a.a2>_2d.max){
|
||||
_2a.a1=_2d.max-_2b;
|
||||
_2a.a2=_2d.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
},applyRatio:function(_2e,_2f,_30,_31){
|
||||
var _32;
|
||||
if(_31=="N"||_31=="S"){
|
||||
_32=this.applyRatioToAxis({a1:_2e.y1,b1:_2e.x1,a2:_2e.y2,b2:_2e.x2},{a:_2f.y,b:_2f.x},{a:_30.y,b:_30.x},{min:0,max:this.imgW});
|
||||
_2e.x1=_32.b1;
|
||||
_2e.y1=_32.a1;
|
||||
_2e.x2=_32.b2;
|
||||
_2e.y2=_32.a2;
|
||||
}else{
|
||||
_32=this.applyRatioToAxis({a1:_2e.x1,b1:_2e.y1,a2:_2e.x2,b2:_2e.y2},{a:_2f.x,b:_2f.y},{a:_30.x,b:_30.y},{min:0,max:this.imgH});
|
||||
_2e.x1=_32.a1;
|
||||
_2e.y1=_32.b1;
|
||||
_2e.x2=_32.a2;
|
||||
_2e.y2=_32.b2;
|
||||
}
|
||||
},applyRatioToAxis:function(_33,_34,_35,_36){
|
||||
var _37=Object.extend(_33,{});
|
||||
var _38=_37.a2-_37.a1;
|
||||
var _3a=Math.floor(_38*_34.b/_34.a);
|
||||
var _3b;
|
||||
var _3c;
|
||||
var _3d=null;
|
||||
if(_35.b==1){
|
||||
_3b=_37.b1+_3a;
|
||||
if(_3b>_36.max){
|
||||
_3b=_36.max;
|
||||
_3d=_3b-_37.b1;
|
||||
}
|
||||
_37.b2=_3b;
|
||||
}else{
|
||||
_3b=_37.b2-_3a;
|
||||
if(_3b<_36.min){
|
||||
_3b=_36.min;
|
||||
_3d=_3b+_37.b2;
|
||||
}
|
||||
_37.b1=_3b;
|
||||
}
|
||||
if(_3d!=null){
|
||||
_3c=Math.floor(_3d*_34.a/_34.b);
|
||||
if(_35.a==1){
|
||||
_37.a2=_37.a1+_3c;
|
||||
}else{
|
||||
_37.a1=_37.a1=_37.a2-_3c;
|
||||
}
|
||||
}
|
||||
return _37;
|
||||
},drawArea:function(){
|
||||
if(!this.isIE){
|
||||
Element.show($(this.overlay));
|
||||
}
|
||||
var _3e=this.calcW();
|
||||
var _3f=this.calcH();
|
||||
var _40=this.areaCoords.x2;
|
||||
var _41=this.areaCoords.y2;
|
||||
var _42=this.selArea.style;
|
||||
_42.left=this.areaCoords.x1+"px";
|
||||
_42.top=this.areaCoords.y1+"px";
|
||||
_42.width=_3e+"px";
|
||||
_42.height=_3f+"px";
|
||||
var _43=Math.ceil((_3e-6)/2)+"px";
|
||||
var _44=Math.ceil((_3f-6)/2)+"px";
|
||||
this.handleN.style.left=_43;
|
||||
this.handleE.style.top=_44;
|
||||
this.handleS.style.left=_43;
|
||||
this.handleW.style.top=_44;
|
||||
if(this.isIE){
|
||||
this.north.style.height=this.areaCoords.y1+"px";
|
||||
var _45=this.east.style;
|
||||
_45.top=this.areaCoords.y1+"px";
|
||||
_45.height=_3f+"px";
|
||||
_45.left=_40+"px";
|
||||
_45.width=(this.img.width-_40)+"px";
|
||||
var _46=this.south.style;
|
||||
_46.top=_41+"px";
|
||||
_46.height=(this.img.height-_41)+"px";
|
||||
var _47=this.west.style;
|
||||
_47.top=this.areaCoords.y1+"px";
|
||||
_47.height=_3f+"px";
|
||||
_47.width=this.areaCoords.x1+"px";
|
||||
}else{
|
||||
_42.backgroundPosition="-"+this.areaCoords.x1+"px "+"-"+this.areaCoords.y1+"px";
|
||||
}
|
||||
this.subDrawArea();
|
||||
this.forceReRender();
|
||||
},forceReRender:function(){
|
||||
if(this.isIE||this.isWebKit){
|
||||
var n=document.createTextNode(" ");
|
||||
var d,el,fixEL,i;
|
||||
if(this.isIE){
|
||||
fixEl=this.selArea;
|
||||
}else{
|
||||
if(this.isWebKit){
|
||||
fixEl=document.getElementsByClassName("imgCrop_marqueeSouth",this.imgWrap)[0];
|
||||
d=Builder.node("div","");
|
||||
d.style.visibility="hidden";
|
||||
var _4a=["SE","S","SW"];
|
||||
for(i=0;i<_4a.length;i++){
|
||||
el=document.getElementsByClassName("imgCrop_handle"+_4a[i],this.selArea)[0];
|
||||
if(el.childNodes.length){
|
||||
el.removeChild(el.childNodes[0]);
|
||||
}
|
||||
el.appendChild(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
fixEl.appendChild(n);
|
||||
fixEl.removeChild(n);
|
||||
}
|
||||
},startResize:function(e){
|
||||
this.startCoords=this.cloneCoords(this.areaCoords);
|
||||
this.resizing=true;
|
||||
this.resizeHandle=Element.classNames(Event.element(e)).toString().replace(/([^N|NE|E|SE|S|SW|W|NW])+/,"");
|
||||
Event.stop(e);
|
||||
},startDrag:function(e){
|
||||
Element.show(this.selArea);
|
||||
this.clickCoords=this.getCurPos(e);
|
||||
this.setAreaCoords({x1:this.clickCoords.x,y1:this.clickCoords.y,x2:this.clickCoords.x,y2:this.clickCoords.y});
|
||||
this.dragging=true;
|
||||
this.onDrag(e);
|
||||
Event.stop(e);
|
||||
},getCurPos:function(e){
|
||||
return curPos={x:Event.pointerX(e)-this.wrapOffsets.left,y:Event.pointerY(e)-this.wrapOffsets.top};
|
||||
},onDrag:function(e){
|
||||
var _4f=null;
|
||||
if(this.dragging||this.resizing){
|
||||
var _50=this.getCurPos(e);
|
||||
var _51=this.cloneCoords(this.areaCoords);
|
||||
var _52={x:1,y:1};
|
||||
}
|
||||
if(this.dragging){
|
||||
if(_50.x<this.clickCoords.x){
|
||||
_52.x=-1;
|
||||
}
|
||||
if(_50.y<this.clickCoords.y){
|
||||
_52.y=-1;
|
||||
}
|
||||
this.transformCoords(_50.x,this.clickCoords.x,_51,"x");
|
||||
this.transformCoords(_50.y,this.clickCoords.y,_51,"y");
|
||||
}else{
|
||||
if(this.resizing){
|
||||
_4f=this.resizeHandle;
|
||||
if(_4f.match(/E/)){
|
||||
this.transformCoords(_50.x,this.startCoords.x1,_51,"x");
|
||||
if(_50.x<this.startCoords.x1){
|
||||
_52.x=-1;
|
||||
}
|
||||
}else{
|
||||
if(_4f.match(/W/)){
|
||||
this.transformCoords(_50.x,this.startCoords.x2,_51,"x");
|
||||
if(_50.x<this.startCoords.x2){
|
||||
_52.x=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_4f.match(/N/)){
|
||||
this.transformCoords(_50.y,this.startCoords.y2,_51,"y");
|
||||
if(_50.y<this.startCoords.y2){
|
||||
_52.y=-1;
|
||||
}
|
||||
}else{
|
||||
if(_4f.match(/S/)){
|
||||
this.transformCoords(_50.y,this.startCoords.y1,_51,"y");
|
||||
if(_50.y<this.startCoords.y1){
|
||||
_52.y=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.dragging||this.resizing){
|
||||
this.setAreaCoords(_51,false,e.shiftKey,_52,_4f);
|
||||
this.drawArea();
|
||||
Event.stop(e);
|
||||
}
|
||||
},transformCoords:function(_53,_54,_55,_56){
|
||||
var _57=new Array();
|
||||
if(_53<_54){
|
||||
_57[0]=_53;
|
||||
_57[1]=_54;
|
||||
}else{
|
||||
_57[0]=_54;
|
||||
_57[1]=_53;
|
||||
}
|
||||
if(_56=="x"){
|
||||
_55.x1=_57[0];
|
||||
_55.x2=_57[1];
|
||||
}else{
|
||||
_55.y1=_57[0];
|
||||
_55.y2=_57[1];
|
||||
}
|
||||
},endCrop:function(){
|
||||
this.dragging=false;
|
||||
this.resizing=false;
|
||||
this.options.onEndCrop(this.areaCoords,{width:this.calcW(),height:this.calcH()});
|
||||
},subInitialize:function(){
|
||||
},subDrawArea:function(){
|
||||
}};
|
||||
Cropper.ImgWithPreview=Class.create();
|
||||
Object.extend(Object.extend(Cropper.ImgWithPreview.prototype,Cropper.Img.prototype),{subInitialize:function(){
|
||||
this.hasPreviewImg=false;
|
||||
if(typeof (this.options.previewWrap)!="undefined"&&this.options.minWidth>0&&this.options.minHeight>0){
|
||||
this.previewWrap=$(this.options.previewWrap);
|
||||
this.previewImg=this.img.cloneNode(false);
|
||||
this.options.displayOnInit=true;
|
||||
this.hasPreviewImg=true;
|
||||
Element.addClassName(this.previewWrap,"imgCrop_previewWrap");
|
||||
Element.setStyle(this.previewWrap,{width:this.options.minWidth+"px",height:this.options.minHeight+"px"});
|
||||
this.previewWrap.appendChild(this.previewImg);
|
||||
}
|
||||
},subDrawArea:function(){
|
||||
if(this.hasPreviewImg){
|
||||
var _58=this.calcW();
|
||||
var _59=this.calcH();
|
||||
var _5a={x:this.imgW/_58,y:this.imgH/_59};
|
||||
var _5b={x:_58/this.options.minWidth,y:_59/this.options.minHeight};
|
||||
var _5c={w:Math.ceil(this.options.minWidth*_5a.x)+"px",h:Math.ceil(this.options.minHeight*_5a.y)+"px",x:"-"+Math.ceil(this.areaCoords.x1/_5b.x)+"px",y:"-"+Math.ceil(this.areaCoords.y1/_5b.y)+"px"};
|
||||
var _5d=this.previewImg.style;
|
||||
_5d.width=_5c.w;
|
||||
_5d.height=_5c.h;
|
||||
_5d.left=_5c.x;
|
||||
_5d.top=_5c.y;
|
||||
}
|
||||
}});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 277 B |
Binary file not shown.
|
After Width: | Height: | Size: 293 B |
@@ -0,0 +1,994 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-base.js
|
||||
*/
|
||||
|
||||
/** @namespace wp */
|
||||
window.wp = window.wp || {};
|
||||
|
||||
(function( exports, $ ){
|
||||
var api = {}, ctor, inherits,
|
||||
slice = Array.prototype.slice;
|
||||
|
||||
// Shared empty constructor function to aid in prototype-chain creation.
|
||||
ctor = function() {};
|
||||
|
||||
/**
|
||||
* Helper function to correctly set up the prototype chain, for subclasses.
|
||||
* Similar to `goog.inherits`, but uses a hash of prototype properties and
|
||||
* class properties to be extended.
|
||||
*
|
||||
* @param object parent Parent class constructor to inherit from.
|
||||
* @param object protoProps Properties to apply to the prototype for use as class instance properties.
|
||||
* @param object staticProps Properties to apply directly to the class constructor.
|
||||
* @return child The subclassed constructor.
|
||||
*/
|
||||
inherits = function( parent, protoProps, staticProps ) {
|
||||
var child;
|
||||
|
||||
/*
|
||||
* The constructor function for the new subclass is either defined by you
|
||||
* (the "constructor" property in your `extend` definition), or defaulted
|
||||
* by us to simply call `super()`.
|
||||
*/
|
||||
if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) {
|
||||
child = protoProps.constructor;
|
||||
} else {
|
||||
child = function() {
|
||||
/*
|
||||
* Storing the result `super()` before returning the value
|
||||
* prevents a bug in Opera where, if the constructor returns
|
||||
* a function, Opera will reject the return value in favor of
|
||||
* the original object. This causes all sorts of trouble.
|
||||
*/
|
||||
var result = parent.apply( this, arguments );
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
// Inherit class (static) properties from parent.
|
||||
$.extend( child, parent );
|
||||
|
||||
// Set the prototype chain to inherit from `parent`,
|
||||
// without calling `parent`'s constructor function.
|
||||
ctor.prototype = parent.prototype;
|
||||
child.prototype = new ctor();
|
||||
|
||||
// Add prototype properties (instance properties) to the subclass,
|
||||
// if supplied.
|
||||
if ( protoProps ) {
|
||||
$.extend( child.prototype, protoProps );
|
||||
}
|
||||
|
||||
// Add static properties to the constructor function, if supplied.
|
||||
if ( staticProps ) {
|
||||
$.extend( child, staticProps );
|
||||
}
|
||||
|
||||
// Correctly set child's `prototype.constructor`.
|
||||
child.prototype.constructor = child;
|
||||
|
||||
// Set a convenience property in case the parent's prototype is needed later.
|
||||
child.__super__ = parent.prototype;
|
||||
|
||||
return child;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for object inheritance.
|
||||
*/
|
||||
api.Class = function( applicator, argsArray, options ) {
|
||||
var magic, args = arguments;
|
||||
|
||||
if ( applicator && argsArray && api.Class.applicator === applicator ) {
|
||||
args = argsArray;
|
||||
$.extend( this, options || {} );
|
||||
}
|
||||
|
||||
magic = this;
|
||||
|
||||
/*
|
||||
* If the class has a method called "instance",
|
||||
* the return value from the class' constructor will be a function that
|
||||
* calls the "instance" method.
|
||||
*
|
||||
* It is also an object that has properties and methods inside it.
|
||||
*/
|
||||
if ( this.instance ) {
|
||||
magic = function() {
|
||||
return magic.instance.apply( magic, arguments );
|
||||
};
|
||||
|
||||
$.extend( magic, this );
|
||||
}
|
||||
|
||||
magic.initialize.apply( magic, args );
|
||||
return magic;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a subclass of the class.
|
||||
*
|
||||
* @param object protoProps Properties to apply to the prototype.
|
||||
* @param object staticProps Properties to apply directly to the class.
|
||||
* @return child The subclass.
|
||||
*/
|
||||
api.Class.extend = function( protoProps, staticProps ) {
|
||||
var child = inherits( this, protoProps, staticProps );
|
||||
child.extend = this.extend;
|
||||
return child;
|
||||
};
|
||||
|
||||
api.Class.applicator = {};
|
||||
|
||||
/**
|
||||
* Initialize a class instance.
|
||||
*
|
||||
* Override this function in a subclass as needed.
|
||||
*/
|
||||
api.Class.prototype.initialize = function() {};
|
||||
|
||||
/*
|
||||
* Checks whether a given instance extended a constructor.
|
||||
*
|
||||
* The magic surrounding the instance parameter causes the instanceof
|
||||
* keyword to return inaccurate results; it defaults to the function's
|
||||
* prototype instead of the constructor chain. Hence this function.
|
||||
*/
|
||||
api.Class.prototype.extended = function( constructor ) {
|
||||
var proto = this;
|
||||
|
||||
while ( typeof proto.constructor !== 'undefined' ) {
|
||||
if ( proto.constructor === constructor ) {
|
||||
return true;
|
||||
}
|
||||
if ( typeof proto.constructor.__super__ === 'undefined' ) {
|
||||
return false;
|
||||
}
|
||||
proto = proto.constructor.__super__;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* An events manager object, offering the ability to bind to and trigger events.
|
||||
*
|
||||
* Used as a mixin.
|
||||
*/
|
||||
api.Events = {
|
||||
trigger: function( id ) {
|
||||
if ( this.topics && this.topics[ id ] ) {
|
||||
this.topics[ id ].fireWith( this, slice.call( arguments, 1 ) );
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
bind: function( id ) {
|
||||
this.topics = this.topics || {};
|
||||
this.topics[ id ] = this.topics[ id ] || $.Callbacks();
|
||||
this.topics[ id ].add.apply( this.topics[ id ], slice.call( arguments, 1 ) );
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind: function( id ) {
|
||||
if ( this.topics && this.topics[ id ] ) {
|
||||
this.topics[ id ].remove.apply( this.topics[ id ], slice.call( arguments, 1 ) );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Observable values that support two-way binding.
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Value
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
api.Value = api.Class.extend(/** @lends wp.customize.Value.prototype */{
|
||||
/**
|
||||
* @param {mixed} initial The initial value.
|
||||
* @param {Object} options
|
||||
*/
|
||||
initialize: function( initial, options ) {
|
||||
this._value = initial; // @todo Potentially change this to a this.set() call.
|
||||
this.callbacks = $.Callbacks();
|
||||
this._dirty = false;
|
||||
|
||||
$.extend( this, options || {} );
|
||||
|
||||
this.set = this.set.bind( this );
|
||||
},
|
||||
|
||||
/*
|
||||
* Magic. Returns a function that will become the instance.
|
||||
* Set to null to prevent the instance from extending a function.
|
||||
*/
|
||||
instance: function() {
|
||||
return arguments.length ? this.set.apply( this, arguments ) : this.get();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the value.
|
||||
*
|
||||
* @return {mixed}
|
||||
*/
|
||||
get: function() {
|
||||
return this._value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the value and trigger all bound callbacks.
|
||||
*
|
||||
* @param {Object} to New value.
|
||||
*/
|
||||
set: function( to ) {
|
||||
var from = this._value;
|
||||
|
||||
to = this._setter.apply( this, arguments );
|
||||
to = this.validate( to );
|
||||
|
||||
// Bail if the sanitized value is null or unchanged.
|
||||
if ( null === to || _.isEqual( from, to ) ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this._value = to;
|
||||
this._dirty = true;
|
||||
|
||||
this.callbacks.fireWith( this, [ to, from ] );
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_setter: function( to ) {
|
||||
return to;
|
||||
},
|
||||
|
||||
setter: function( callback ) {
|
||||
var from = this.get();
|
||||
this._setter = callback;
|
||||
// Temporarily clear value so setter can decide if it's valid.
|
||||
this._value = null;
|
||||
this.set( from );
|
||||
return this;
|
||||
},
|
||||
|
||||
resetSetter: function() {
|
||||
this._setter = this.constructor.prototype._setter;
|
||||
this.set( this.get() );
|
||||
return this;
|
||||
},
|
||||
|
||||
validate: function( value ) {
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind a function to be invoked whenever the value changes.
|
||||
*
|
||||
* @param {...Function} A function, or multiple functions, to add to the callback stack.
|
||||
*/
|
||||
bind: function() {
|
||||
this.callbacks.add.apply( this.callbacks, arguments );
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Unbind a previously bound function.
|
||||
*
|
||||
* @param {...Function} A function, or multiple functions, to remove from the callback stack.
|
||||
*/
|
||||
unbind: function() {
|
||||
this.callbacks.remove.apply( this.callbacks, arguments );
|
||||
return this;
|
||||
},
|
||||
|
||||
link: function() { // values*
|
||||
var set = this.set;
|
||||
$.each( arguments, function() {
|
||||
this.bind( set );
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
unlink: function() { // values*
|
||||
var set = this.set;
|
||||
$.each( arguments, function() {
|
||||
this.unbind( set );
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
sync: function() { // values*
|
||||
var that = this;
|
||||
$.each( arguments, function() {
|
||||
that.link( this );
|
||||
this.link( that );
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
unsync: function() { // values*
|
||||
var that = this;
|
||||
$.each( arguments, function() {
|
||||
that.unlink( this );
|
||||
this.unlink( that );
|
||||
});
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A collection of observable values.
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Values
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Class
|
||||
* @mixes wp.customize.Events
|
||||
*/
|
||||
api.Values = api.Class.extend(/** @lends wp.customize.Values.prototype */{
|
||||
|
||||
/**
|
||||
* The default constructor for items of the collection.
|
||||
*
|
||||
* @type {object}
|
||||
*/
|
||||
defaultConstructor: api.Value,
|
||||
|
||||
initialize: function( options ) {
|
||||
$.extend( this, options || {} );
|
||||
|
||||
this._value = {};
|
||||
this._deferreds = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the instance of an item from the collection if only ID is specified.
|
||||
*
|
||||
* If more than one argument is supplied, all are expected to be IDs and
|
||||
* the last to be a function callback that will be invoked when the requested
|
||||
* items are available.
|
||||
*
|
||||
* @see {api.Values.when}
|
||||
*
|
||||
* @param {string} id ID of the item.
|
||||
* @param {...} Zero or more IDs of items to wait for and a callback
|
||||
* function to invoke when they're available. Optional.
|
||||
* @return {mixed} The item instance if only one ID was supplied.
|
||||
* A Deferred Promise object if a callback function is supplied.
|
||||
*/
|
||||
instance: function( id ) {
|
||||
if ( arguments.length === 1 ) {
|
||||
return this.value( id );
|
||||
}
|
||||
|
||||
return this.when.apply( this, arguments );
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the instance of an item.
|
||||
*
|
||||
* @param {string} id The ID of the item.
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
value: function( id ) {
|
||||
return this._value[ id ];
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the collection has an item with the given ID.
|
||||
*
|
||||
* @param {string} id The ID of the item to look for.
|
||||
* @return {boolean}
|
||||
*/
|
||||
has: function( id ) {
|
||||
return typeof this._value[ id ] !== 'undefined';
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an item to the collection.
|
||||
*
|
||||
* @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add.
|
||||
* When an ID string is supplied, then itemObject must be provided.
|
||||
* @param {wp.customize.Class} [itemObject] - The item instance when the first argument is an ID string.
|
||||
* @return {wp.customize.Class} The new item's instance, or an existing instance if already added.
|
||||
*/
|
||||
add: function( item, itemObject ) {
|
||||
var collection = this, id, instance;
|
||||
if ( 'string' === typeof item ) {
|
||||
id = item;
|
||||
instance = itemObject;
|
||||
} else {
|
||||
if ( 'string' !== typeof item.id ) {
|
||||
throw new Error( 'Unknown key' );
|
||||
}
|
||||
id = item.id;
|
||||
instance = item;
|
||||
}
|
||||
|
||||
if ( collection.has( id ) ) {
|
||||
return collection.value( id );
|
||||
}
|
||||
|
||||
collection._value[ id ] = instance;
|
||||
instance.parent = collection;
|
||||
|
||||
// Propagate a 'change' event on an item up to the collection.
|
||||
if ( instance.extended( api.Value ) ) {
|
||||
instance.bind( collection._change );
|
||||
}
|
||||
|
||||
collection.trigger( 'add', instance );
|
||||
|
||||
// If a deferred object exists for this item,
|
||||
// resolve it.
|
||||
if ( collection._deferreds[ id ] ) {
|
||||
collection._deferreds[ id ].resolve();
|
||||
}
|
||||
|
||||
return collection._value[ id ];
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new item of the collection using the collection's default constructor
|
||||
* and store it in the collection.
|
||||
*
|
||||
* @param {string} id The ID of the item.
|
||||
* @param {mixed} value Any extra arguments are passed into the item's initialize method.
|
||||
* @return {mixed} The new item's instance.
|
||||
*/
|
||||
create: function( id ) {
|
||||
return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterate over all items in the collection invoking the provided callback.
|
||||
*
|
||||
* @param {Function} callback Function to invoke.
|
||||
* @param {Object} context Object context to invoke the function with. Optional.
|
||||
*/
|
||||
each: function( callback, context ) {
|
||||
context = typeof context === 'undefined' ? this : context;
|
||||
|
||||
$.each( this._value, function( key, obj ) {
|
||||
callback.call( context, obj, key );
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an item from the collection.
|
||||
*
|
||||
* @param {string} id The ID of the item to remove.
|
||||
*/
|
||||
remove: function( id ) {
|
||||
var value = this.value( id );
|
||||
|
||||
if ( value ) {
|
||||
|
||||
// Trigger event right before the element is removed from the collection.
|
||||
this.trigger( 'remove', value );
|
||||
|
||||
if ( value.extended( api.Value ) ) {
|
||||
value.unbind( this._change );
|
||||
}
|
||||
delete value.parent;
|
||||
}
|
||||
|
||||
delete this._value[ id ];
|
||||
delete this._deferreds[ id ];
|
||||
|
||||
// Trigger removed event after the item has been eliminated from the collection.
|
||||
if ( value ) {
|
||||
this.trigger( 'removed', value );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Runs a callback once all requested values exist.
|
||||
*
|
||||
* when( ids*, [callback] );
|
||||
*
|
||||
* For example:
|
||||
* when( id1, id2, id3, function( value1, value2, value3 ) {} );
|
||||
*
|
||||
* @return $.Deferred.promise();
|
||||
*/
|
||||
when: function() {
|
||||
var self = this,
|
||||
ids = slice.call( arguments ),
|
||||
dfd = $.Deferred();
|
||||
|
||||
// If the last argument is a callback, bind it to .done().
|
||||
if ( typeof ids[ ids.length - 1 ] === 'function' ) {
|
||||
dfd.done( ids.pop() );
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a stack of deferred objects for each item that is not
|
||||
* yet available, and invoke the supplied callback when they are.
|
||||
*/
|
||||
$.when.apply( $, $.map( ids, function( id ) {
|
||||
if ( self.has( id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The requested item is not available yet, create a deferred
|
||||
* object to resolve when it becomes available.
|
||||
*/
|
||||
return self._deferreds[ id ] = self._deferreds[ id ] || $.Deferred();
|
||||
})).done( function() {
|
||||
var values = $.map( ids, function( id ) {
|
||||
return self( id );
|
||||
});
|
||||
|
||||
// If a value is missing, we've used at least one expired deferred.
|
||||
// Call Values.when again to generate a new deferred.
|
||||
if ( values.length !== ids.length ) {
|
||||
// ids.push( callback );
|
||||
self.when.apply( self, ids ).done( function() {
|
||||
dfd.resolveWith( self, values );
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dfd.resolveWith( self, values );
|
||||
});
|
||||
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function to propagate a 'change' event from an item
|
||||
* to the collection itself.
|
||||
*/
|
||||
_change: function() {
|
||||
this.parent.trigger( 'change', this );
|
||||
}
|
||||
});
|
||||
|
||||
// Create a global events bus on the Customizer.
|
||||
$.extend( api.Values.prototype, api.Events );
|
||||
|
||||
|
||||
/**
|
||||
* Cast a string to a jQuery collection if it isn't already.
|
||||
*
|
||||
* @param {string|jQuery collection} element
|
||||
*/
|
||||
api.ensure = function( element ) {
|
||||
return typeof element === 'string' ? $( element ) : element;
|
||||
};
|
||||
|
||||
/**
|
||||
* An observable value that syncs with an element.
|
||||
*
|
||||
* Handles inputs, selects, and textareas by default.
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Element
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Value
|
||||
* @augments wp.customize.Class
|
||||
*/
|
||||
api.Element = api.Value.extend(/** @lends wp.customize.Element */{
|
||||
initialize: function( element, options ) {
|
||||
var self = this,
|
||||
synchronizer = api.Element.synchronizer.html,
|
||||
type, update, refresh;
|
||||
|
||||
this.element = api.ensure( element );
|
||||
this.events = '';
|
||||
|
||||
if ( this.element.is( 'input, select, textarea' ) ) {
|
||||
type = this.element.prop( 'type' );
|
||||
this.events += ' change input';
|
||||
synchronizer = api.Element.synchronizer.val;
|
||||
|
||||
if ( this.element.is( 'input' ) && api.Element.synchronizer[ type ] ) {
|
||||
synchronizer = api.Element.synchronizer[ type ];
|
||||
}
|
||||
}
|
||||
|
||||
api.Value.prototype.initialize.call( this, null, $.extend( options || {}, synchronizer ) );
|
||||
this._value = this.get();
|
||||
|
||||
update = this.update;
|
||||
refresh = this.refresh;
|
||||
|
||||
this.update = function( to ) {
|
||||
if ( to !== refresh.call( self ) ) {
|
||||
update.apply( this, arguments );
|
||||
}
|
||||
};
|
||||
this.refresh = function() {
|
||||
self.set( refresh.call( self ) );
|
||||
};
|
||||
|
||||
this.bind( this.update );
|
||||
this.element.on( this.events, this.refresh );
|
||||
},
|
||||
|
||||
find: function( selector ) {
|
||||
return $( selector, this.element );
|
||||
},
|
||||
|
||||
refresh: function() {},
|
||||
|
||||
update: function() {}
|
||||
});
|
||||
|
||||
api.Element.synchronizer = {};
|
||||
|
||||
$.each( [ 'html', 'val' ], function( index, method ) {
|
||||
api.Element.synchronizer[ method ] = {
|
||||
update: function( to ) {
|
||||
this.element[ method ]( to );
|
||||
},
|
||||
refresh: function() {
|
||||
return this.element[ method ]();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
api.Element.synchronizer.checkbox = {
|
||||
update: function( to ) {
|
||||
this.element.prop( 'checked', to );
|
||||
},
|
||||
refresh: function() {
|
||||
return this.element.prop( 'checked' );
|
||||
}
|
||||
};
|
||||
|
||||
api.Element.synchronizer.radio = {
|
||||
update: function( to ) {
|
||||
this.element.filter( function() {
|
||||
return this.value === to;
|
||||
}).prop( 'checked', true );
|
||||
},
|
||||
refresh: function() {
|
||||
return this.element.filter( ':checked' ).val();
|
||||
}
|
||||
};
|
||||
|
||||
$.support.postMessage = !! window.postMessage;
|
||||
|
||||
/**
|
||||
* A communicator for sending data from one window to another over postMessage.
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Messenger
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Class
|
||||
* @mixes wp.customize.Events
|
||||
*/
|
||||
api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{
|
||||
/**
|
||||
* Create a new Value.
|
||||
*
|
||||
* @param {string} key Unique identifier.
|
||||
* @param {mixed} initial Initial value.
|
||||
* @param {mixed} options Options hash. Optional.
|
||||
* @return {Value} Class instance of the Value.
|
||||
*/
|
||||
add: function( key, initial, options ) {
|
||||
return this[ key ] = new api.Value( initial, options );
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize Messenger.
|
||||
*
|
||||
* @param {Object} params - Parameters to configure the messenger.
|
||||
* {string} params.url - The URL to communicate with.
|
||||
* {window} params.targetWindow - The window instance to communicate with. Default window.parent.
|
||||
* {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel.
|
||||
* @param {Object} options - Extend any instance parameter or method with this object.
|
||||
*/
|
||||
initialize: function( params, options ) {
|
||||
// Target the parent frame by default, but only if a parent frame exists.
|
||||
var defaultTarget = window.parent === window ? null : window.parent;
|
||||
|
||||
$.extend( this, options || {} );
|
||||
|
||||
this.add( 'channel', params.channel );
|
||||
this.add( 'url', params.url || '' );
|
||||
this.add( 'origin', this.url() ).link( this.url ).setter( function( to ) {
|
||||
var urlParser = document.createElement( 'a' );
|
||||
urlParser.href = to;
|
||||
// Port stripping needed by IE since it adds to host but not to event.origin.
|
||||
return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' );
|
||||
});
|
||||
|
||||
// First add with no value.
|
||||
this.add( 'targetWindow', null );
|
||||
// This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios.
|
||||
this.targetWindow.set = function( to ) {
|
||||
var from = this._value;
|
||||
|
||||
to = this._setter.apply( this, arguments );
|
||||
to = this.validate( to );
|
||||
|
||||
if ( null === to || from === to ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this._value = to;
|
||||
this._dirty = true;
|
||||
|
||||
this.callbacks.fireWith( this, [ to, from ] );
|
||||
|
||||
return this;
|
||||
};
|
||||
// Now set it.
|
||||
this.targetWindow( params.targetWindow || defaultTarget );
|
||||
|
||||
|
||||
/*
|
||||
* Since we want jQuery to treat the receive function as unique
|
||||
* to this instance, we give the function a new guid.
|
||||
*
|
||||
* This will prevent every Messenger's receive function from being
|
||||
* unbound when calling $.off( 'message', this.receive );
|
||||
*/
|
||||
this.receive = this.receive.bind( this );
|
||||
this.receive.guid = $.guid++;
|
||||
|
||||
$( window ).on( 'message', this.receive );
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
$( window ).off( 'message', this.receive );
|
||||
},
|
||||
|
||||
/**
|
||||
* Receive data from the other window.
|
||||
*
|
||||
* @param {jQuery.Event} event Event with embedded data.
|
||||
*/
|
||||
receive: function( event ) {
|
||||
var message;
|
||||
|
||||
event = event.originalEvent;
|
||||
|
||||
if ( ! this.targetWindow || ! this.targetWindow() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to make sure the origin is valid.
|
||||
if ( this.origin() && event.origin !== this.origin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure we have a string that's JSON.parse-able.
|
||||
if ( typeof event.data !== 'string' || event.data[0] !== '{' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = JSON.parse( event.data );
|
||||
|
||||
// Check required message properties.
|
||||
if ( ! message || ! message.id || typeof message.data === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if channel names match.
|
||||
if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.trigger( message.id, message.data );
|
||||
},
|
||||
|
||||
/**
|
||||
* Send data to the other window.
|
||||
*
|
||||
* @param {string} id The event name.
|
||||
* @param {Object} data Data.
|
||||
*/
|
||||
send: function( id, data ) {
|
||||
var message;
|
||||
|
||||
data = typeof data === 'undefined' ? null : data;
|
||||
|
||||
if ( ! this.url() || ! this.targetWindow() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = { id: id, data: data };
|
||||
if ( this.channel() ) {
|
||||
message.channel = this.channel();
|
||||
}
|
||||
|
||||
this.targetWindow().postMessage( JSON.stringify( message ), this.origin() );
|
||||
}
|
||||
});
|
||||
|
||||
// Add the Events mixin to api.Messenger.
|
||||
$.extend( api.Messenger.prototype, api.Events );
|
||||
|
||||
/**
|
||||
* Notification.
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.Class
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Notification
|
||||
*
|
||||
* @param {string} code - The error code.
|
||||
* @param {object} params - Params.
|
||||
* @param {string} params.message=null - The error message.
|
||||
* @param {string} [params.type=error] - The notification type.
|
||||
* @param {boolean} [params.fromServer=false] - Whether the notification was server-sent.
|
||||
* @param {string} [params.setting=null] - The setting ID that the notification is related to.
|
||||
* @param {*} [params.data=null] - Any additional data.
|
||||
*/
|
||||
api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{
|
||||
|
||||
/**
|
||||
* Template function for rendering the notification.
|
||||
*
|
||||
* This will be populated with template option or else it will be populated with template from the ID.
|
||||
*
|
||||
* @since 4.9.0
|
||||
* @var {Function}
|
||||
*/
|
||||
template: null,
|
||||
|
||||
/**
|
||||
* ID for the template to render the notification.
|
||||
*
|
||||
* @since 4.9.0
|
||||
* @var {string}
|
||||
*/
|
||||
templateId: 'customize-notification',
|
||||
|
||||
/**
|
||||
* Additional class names to add to the notification container.
|
||||
*
|
||||
* @since 4.9.0
|
||||
* @var {string}
|
||||
*/
|
||||
containerClasses: '',
|
||||
|
||||
/**
|
||||
* Initialize notification.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @param {string} code - Notification code.
|
||||
* @param {Object} params - Notification parameters.
|
||||
* @param {string} params.message - Message.
|
||||
* @param {string} [params.type=error] - Type.
|
||||
* @param {string} [params.setting] - Related setting ID.
|
||||
* @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
|
||||
* @param {string} [params.templateId] - ID for template to render the notification.
|
||||
* @param {string} [params.containerClasses] - Additional class names to add to the notification container.
|
||||
* @param {boolean} [params.dismissible] - Whether the notification can be dismissed.
|
||||
*/
|
||||
initialize: function( code, params ) {
|
||||
var _params;
|
||||
this.code = code;
|
||||
_params = _.extend(
|
||||
{
|
||||
message: null,
|
||||
type: 'error',
|
||||
fromServer: false,
|
||||
data: null,
|
||||
setting: null,
|
||||
template: null,
|
||||
dismissible: false,
|
||||
containerClasses: ''
|
||||
},
|
||||
params
|
||||
);
|
||||
delete _params.code;
|
||||
_.extend( this, _params );
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the notification.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @return {jQuery} Notification container element.
|
||||
*/
|
||||
render: function() {
|
||||
var notification = this, container, data;
|
||||
if ( ! notification.template ) {
|
||||
notification.template = wp.template( notification.templateId );
|
||||
}
|
||||
data = _.extend( {}, notification, {
|
||||
alt: notification.parent && notification.parent.alt
|
||||
} );
|
||||
container = $( notification.template( data ) );
|
||||
|
||||
if ( notification.dismissible ) {
|
||||
container.find( '.notice-dismiss' ).on( 'click keydown', function( event ) {
|
||||
if ( 'keydown' === event.type && 13 !== event.which ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( notification.parent ) {
|
||||
notification.parent.remove( notification.code );
|
||||
} else {
|
||||
container.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
// The main API object is also a collection of all customizer settings.
|
||||
api = $.extend( new api.Values(), api );
|
||||
|
||||
/**
|
||||
* Get all customize settings.
|
||||
*
|
||||
* @alias wp.customize.get
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
api.get = function() {
|
||||
var result = {};
|
||||
|
||||
this.each( function( obj, key ) {
|
||||
result[ key ] = obj.get();
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility function namespace
|
||||
*
|
||||
* @namespace wp.customize.utils
|
||||
*/
|
||||
api.utils = {};
|
||||
|
||||
/**
|
||||
* Parse query string.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access public
|
||||
*
|
||||
* @alias wp.customize.utils.parseQueryString
|
||||
*
|
||||
* @param {string} queryString Query string.
|
||||
* @return {Object} Parsed query string.
|
||||
*/
|
||||
api.utils.parseQueryString = function parseQueryString( queryString ) {
|
||||
var queryParams = {};
|
||||
_.each( queryString.split( '&' ), function( pair ) {
|
||||
var parts, key, value;
|
||||
parts = pair.split( '=', 2 );
|
||||
if ( ! parts[0] ) {
|
||||
return;
|
||||
}
|
||||
key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
|
||||
key = key.replace( / /g, '_' ); // What PHP does.
|
||||
if ( _.isUndefined( parts[1] ) ) {
|
||||
value = null;
|
||||
} else {
|
||||
value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
|
||||
}
|
||||
queryParams[ key ] = value;
|
||||
} );
|
||||
return queryParams;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose the API publicly on window.wp.customize
|
||||
*
|
||||
* @namespace wp.customize
|
||||
*/
|
||||
exports.customize = api;
|
||||
})( wp, jQuery );
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-loader.js
|
||||
*/
|
||||
|
||||
/* global _wpCustomizeLoaderSettings */
|
||||
|
||||
/**
|
||||
* Expose a public API that allows the customizer to be
|
||||
* loaded on any page.
|
||||
*
|
||||
* @namespace wp
|
||||
*/
|
||||
window.wp = window.wp || {};
|
||||
|
||||
(function( exports, $ ){
|
||||
var api = wp.customize,
|
||||
Loader;
|
||||
|
||||
$.extend( $.support, {
|
||||
history: !! ( window.history && history.pushState ),
|
||||
hashchange: ('onhashchange' in window) && (document.documentMode === undefined || document.documentMode > 7)
|
||||
});
|
||||
|
||||
/**
|
||||
* Allows the Customizer to be overlayed on any page.
|
||||
*
|
||||
* By default, any element in the body with the load-customize class will open
|
||||
* an iframe overlay with the URL specified.
|
||||
*
|
||||
* e.g. <a class="load-customize" href="<?php echo wp_customize_url(); ?>">Open Customizer</a>
|
||||
*
|
||||
* @memberOf wp.customize
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.Events
|
||||
*/
|
||||
Loader = $.extend( {}, api.Events,/** @lends wp.customize.Loader.prototype */{
|
||||
/**
|
||||
* Setup the Loader; triggered on document#ready.
|
||||
*/
|
||||
initialize: function() {
|
||||
this.body = $( document.body );
|
||||
|
||||
// Ensure the loader is supported.
|
||||
// Check for settings, postMessage support, and whether we require CORS support.
|
||||
if ( ! Loader.settings || ! $.support.postMessage || ( ! $.support.cors && Loader.settings.isCrossDomain ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.window = $( window );
|
||||
this.element = $( '<div id="customize-container" />' ).appendTo( this.body );
|
||||
|
||||
// Bind events for opening and closing the overlay.
|
||||
this.bind( 'open', this.overlay.show );
|
||||
this.bind( 'close', this.overlay.hide );
|
||||
|
||||
// Any element in the body with the `load-customize` class opens
|
||||
// the Customizer.
|
||||
$('#wpbody').on( 'click', '.load-customize', function( event ) {
|
||||
event.preventDefault();
|
||||
|
||||
// Store a reference to the link that opened the Customizer.
|
||||
Loader.link = $(this);
|
||||
// Load the theme.
|
||||
Loader.open( Loader.link.attr('href') );
|
||||
});
|
||||
|
||||
// Add navigation listeners.
|
||||
if ( $.support.history ) {
|
||||
this.window.on( 'popstate', Loader.popstate );
|
||||
}
|
||||
|
||||
if ( $.support.hashchange ) {
|
||||
this.window.on( 'hashchange', Loader.hashchange );
|
||||
this.window.triggerHandler( 'hashchange' );
|
||||
}
|
||||
},
|
||||
|
||||
popstate: function( e ) {
|
||||
var state = e.originalEvent.state;
|
||||
if ( state && state.customize ) {
|
||||
Loader.open( state.customize );
|
||||
} else if ( Loader.active ) {
|
||||
Loader.close();
|
||||
}
|
||||
},
|
||||
|
||||
hashchange: function() {
|
||||
var hash = window.location.toString().split('#')[1];
|
||||
|
||||
if ( hash && 0 === hash.indexOf( 'wp_customize=on' ) ) {
|
||||
Loader.open( Loader.settings.url + '?' + hash );
|
||||
}
|
||||
|
||||
if ( ! hash && ! $.support.history ) {
|
||||
Loader.close();
|
||||
}
|
||||
},
|
||||
|
||||
beforeunload: function () {
|
||||
if ( ! Loader.saved() ) {
|
||||
return Loader.settings.l10n.saveAlert;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the Customizer overlay for a specific URL.
|
||||
*
|
||||
* @param string src URL to load in the Customizer.
|
||||
*/
|
||||
open: function( src ) {
|
||||
|
||||
if ( this.active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the full page on mobile devices.
|
||||
if ( Loader.settings.browser.mobile ) {
|
||||
return window.location = src;
|
||||
}
|
||||
|
||||
// Store the document title prior to opening the Live Preview.
|
||||
this.originalDocumentTitle = document.title;
|
||||
|
||||
this.active = true;
|
||||
this.body.addClass('customize-loading');
|
||||
|
||||
/*
|
||||
* Track the dirtiness state (whether the drafted changes have been published)
|
||||
* of the Customizer in the iframe. This is used to decide whether to display
|
||||
* an AYS alert if the user tries to close the window before saving changes.
|
||||
*/
|
||||
this.saved = new api.Value( true );
|
||||
|
||||
this.iframe = $( '<iframe />', { 'src': src, 'title': Loader.settings.l10n.mainIframeTitle } ).appendTo( this.element );
|
||||
this.iframe.one( 'load', this.loaded );
|
||||
|
||||
// Create a postMessage connection with the iframe.
|
||||
this.messenger = new api.Messenger({
|
||||
url: src,
|
||||
channel: 'loader',
|
||||
targetWindow: this.iframe[0].contentWindow
|
||||
});
|
||||
|
||||
// Expose the changeset UUID on the parent window's URL so that the customized state can survive a refresh.
|
||||
if ( history.replaceState ) {
|
||||
this.messenger.bind( 'changeset-uuid', function( changesetUuid ) {
|
||||
var urlParser = document.createElement( 'a' );
|
||||
urlParser.href = location.href;
|
||||
urlParser.search = $.param( _.extend(
|
||||
api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
|
||||
{ changeset_uuid: changesetUuid }
|
||||
) );
|
||||
history.replaceState( { customize: urlParser.href }, '', urlParser.href );
|
||||
} );
|
||||
}
|
||||
|
||||
// Wait for the connection from the iframe before sending any postMessage events.
|
||||
this.messenger.bind( 'ready', function() {
|
||||
Loader.messenger.send( 'back' );
|
||||
});
|
||||
|
||||
this.messenger.bind( 'close', function() {
|
||||
if ( $.support.history ) {
|
||||
history.back();
|
||||
} else if ( $.support.hashchange ) {
|
||||
window.location.hash = '';
|
||||
} else {
|
||||
Loader.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt AYS dialog when navigating away.
|
||||
$( window ).on( 'beforeunload', this.beforeunload );
|
||||
|
||||
this.messenger.bind( 'saved', function () {
|
||||
Loader.saved( true );
|
||||
} );
|
||||
this.messenger.bind( 'change', function () {
|
||||
Loader.saved( false );
|
||||
} );
|
||||
|
||||
this.messenger.bind( 'title', function( newTitle ){
|
||||
window.document.title = newTitle;
|
||||
});
|
||||
|
||||
this.pushState( src );
|
||||
|
||||
this.trigger( 'open' );
|
||||
},
|
||||
|
||||
pushState: function ( src ) {
|
||||
var hash = src.split( '?' )[1];
|
||||
|
||||
// Ensure we don't call pushState if the user hit the forward button.
|
||||
if ( $.support.history && window.location.href !== src ) {
|
||||
history.pushState( { customize: src }, '', src );
|
||||
} else if ( ! $.support.history && $.support.hashchange && hash ) {
|
||||
window.location.hash = 'wp_customize=on&' + hash;
|
||||
}
|
||||
|
||||
this.trigger( 'open' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback after the Customizer has been opened.
|
||||
*/
|
||||
opened: function() {
|
||||
Loader.body.addClass( 'customize-active full-overlay-active' ).attr( 'aria-busy', 'true' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the Customizer overlay.
|
||||
*/
|
||||
close: function() {
|
||||
var self = this, onConfirmClose;
|
||||
if ( ! self.active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
onConfirmClose = function( confirmed ) {
|
||||
if ( confirmed ) {
|
||||
self.active = false;
|
||||
self.trigger( 'close' );
|
||||
|
||||
// Restore document title prior to opening the Live Preview.
|
||||
if ( self.originalDocumentTitle ) {
|
||||
document.title = self.originalDocumentTitle;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Go forward since Customizer is exited by history.back().
|
||||
history.forward();
|
||||
}
|
||||
self.messenger.unbind( 'confirmed-close', onConfirmClose );
|
||||
};
|
||||
self.messenger.bind( 'confirmed-close', onConfirmClose );
|
||||
|
||||
Loader.messenger.send( 'confirm-close' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback after the Customizer has been closed.
|
||||
*/
|
||||
closed: function() {
|
||||
Loader.iframe.remove();
|
||||
Loader.messenger.destroy();
|
||||
Loader.iframe = null;
|
||||
Loader.messenger = null;
|
||||
Loader.saved = null;
|
||||
Loader.body.removeClass( 'customize-active full-overlay-active' ).removeClass( 'customize-loading' );
|
||||
$( window ).off( 'beforeunload', Loader.beforeunload );
|
||||
/*
|
||||
* Return focus to the link that opened the Customizer overlay after
|
||||
* the body element visibility is restored.
|
||||
*/
|
||||
if ( Loader.link ) {
|
||||
Loader.link.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for the `load` event on the Customizer iframe.
|
||||
*/
|
||||
loaded: function() {
|
||||
Loader.body.removeClass( 'customize-loading' ).attr( 'aria-busy', 'false' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Overlay hide/show utility methods.
|
||||
*/
|
||||
overlay: {
|
||||
show: function() {
|
||||
this.element.fadeIn( 200, Loader.opened );
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.element.fadeOut( 200, Loader.closed );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Bootstrap the Loader on document#ready.
|
||||
$( function() {
|
||||
Loader.settings = _wpCustomizeLoaderSettings;
|
||||
Loader.initialize();
|
||||
});
|
||||
|
||||
// Expose the API publicly on window.wp.customize.Loader.
|
||||
api.Loader = Loader;
|
||||
})( wp, jQuery );
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
window.wp=window.wp||{},function(i){var n,o=wp.customize;i.extend(i.support,{history:!(!window.history||!history.pushState),hashchange:"onhashchange"in window&&(void 0===document.documentMode||7<document.documentMode)}),n=i.extend({},o.Events,{initialize:function(){this.body=i(document.body),n.settings&&i.support.postMessage&&(i.support.cors||!n.settings.isCrossDomain)&&(this.window=i(window),this.element=i('<div id="customize-container" />').appendTo(this.body),this.bind("open",this.overlay.show),this.bind("close",this.overlay.hide),i("#wpbody").on("click",".load-customize",function(e){e.preventDefault(),n.link=i(this),n.open(n.link.attr("href"))}),i.support.history&&this.window.on("popstate",n.popstate),i.support.hashchange)&&(this.window.on("hashchange",n.hashchange),this.window.triggerHandler("hashchange"))},popstate:function(e){e=e.originalEvent.state;e&&e.customize?n.open(e.customize):n.active&&n.close()},hashchange:function(){var e=window.location.toString().split("#")[1];e&&0===e.indexOf("wp_customize=on")&&n.open(n.settings.url+"?"+e),e||i.support.history||n.close()},beforeunload:function(){if(!n.saved())return n.settings.l10n.saveAlert},open:function(e){if(!this.active){if(n.settings.browser.mobile)return window.location=e;this.originalDocumentTitle=document.title,this.active=!0,this.body.addClass("customize-loading"),this.saved=new o.Value(!0),this.iframe=i("<iframe />",{src:e,title:n.settings.l10n.mainIframeTitle}).appendTo(this.element),this.iframe.one("load",this.loaded),this.messenger=new o.Messenger({url:e,channel:"loader",targetWindow:this.iframe[0].contentWindow}),history.replaceState&&this.messenger.bind("changeset-uuid",function(e){var t=document.createElement("a");t.href=location.href,t.search=i.param(_.extend(o.utils.parseQueryString(t.search.substr(1)),{changeset_uuid:e})),history.replaceState({customize:t.href},"",t.href)}),this.messenger.bind("ready",function(){n.messenger.send("back")}),this.messenger.bind("close",function(){i.support.history?history.back():i.support.hashchange?window.location.hash="":n.close()}),i(window).on("beforeunload",this.beforeunload),this.messenger.bind("saved",function(){n.saved(!0)}),this.messenger.bind("change",function(){n.saved(!1)}),this.messenger.bind("title",function(e){window.document.title=e}),this.pushState(e),this.trigger("open")}},pushState:function(e){var t=e.split("?")[1];i.support.history&&window.location.href!==e?history.pushState({customize:e},"",e):!i.support.history&&i.support.hashchange&&t&&(window.location.hash="wp_customize=on&"+t),this.trigger("open")},opened:function(){n.body.addClass("customize-active full-overlay-active").attr("aria-busy","true")},close:function(){var t,i=this;i.active&&(i.messenger.bind("confirmed-close",t=function(e){e?(i.active=!1,i.trigger("close"),i.originalDocumentTitle&&(document.title=i.originalDocumentTitle)):history.forward(),i.messenger.unbind("confirmed-close",t)}),n.messenger.send("confirm-close"))},closed:function(){n.iframe.remove(),n.messenger.destroy(),n.iframe=null,n.messenger=null,n.saved=null,n.body.removeClass("customize-active full-overlay-active").removeClass("customize-loading"),i(window).off("beforeunload",n.beforeunload),n.link&&n.link.focus()},loaded:function(){n.body.removeClass("customize-loading").attr("aria-busy","false")},overlay:{show:function(){this.element.fadeIn(200,n.opened)},hide:function(){this.element.fadeOut(200,n.closed)}}}),i(function(){n.settings=_wpCustomizeLoaderSettings,n.initialize()}),o.Loader=n}((wp,jQuery));
|
||||
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-models.js
|
||||
*/
|
||||
|
||||
/* global _wpCustomizeHeader */
|
||||
(function( $, wp ) {
|
||||
var api = wp.customize;
|
||||
/** @namespace wp.customize.HeaderTool */
|
||||
api.HeaderTool = {};
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ImageModel
|
||||
*
|
||||
* A header image. This is where saves via the Customizer API are
|
||||
* abstracted away, plus our own Ajax calls to add images to and remove
|
||||
* images from the user's recently uploaded images setting on the server.
|
||||
* These calls are made regardless of whether the user actually saves new
|
||||
* Customizer settings.
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.ImageModel
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
api.HeaderTool.ImageModel = Backbone.Model.extend(/** @lends wp.customize.HeaderTool.ImageModel.prototype */{
|
||||
defaults: function() {
|
||||
return {
|
||||
header: {
|
||||
attachment_id: 0,
|
||||
url: '',
|
||||
timestamp: _.now(),
|
||||
thumbnail_url: ''
|
||||
},
|
||||
choice: '',
|
||||
selected: false,
|
||||
random: false
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.on('hide', this.hide, this);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.set('choice', '');
|
||||
api('header_image').set('remove-header');
|
||||
api('header_image_data').set('remove-header');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var data = this.get('header'),
|
||||
curr = api.HeaderTool.currentHeader.get('header').attachment_id;
|
||||
|
||||
// If the image we're removing is also the current header,
|
||||
// unset the latter.
|
||||
if (curr && data.attachment_id === curr) {
|
||||
api.HeaderTool.currentHeader.trigger('hide');
|
||||
}
|
||||
|
||||
wp.ajax.post( 'custom-header-remove', {
|
||||
nonce: _wpCustomizeHeader.nonces.remove,
|
||||
wp_customize: 'on',
|
||||
theme: api.settings.theme.stylesheet,
|
||||
attachment_id: data.attachment_id
|
||||
});
|
||||
|
||||
this.trigger('destroy', this, this.collection);
|
||||
},
|
||||
|
||||
save: function() {
|
||||
if (this.get('random')) {
|
||||
api('header_image').set(this.get('header').random);
|
||||
api('header_image_data').set(this.get('header').random);
|
||||
} else {
|
||||
if (this.get('header').defaultName) {
|
||||
api('header_image').set(this.get('header').url);
|
||||
api('header_image_data').set(this.get('header').defaultName);
|
||||
} else {
|
||||
api('header_image').set(this.get('header').url);
|
||||
api('header_image_data').set(this.get('header'));
|
||||
}
|
||||
}
|
||||
|
||||
api.HeaderTool.combinedList.trigger('control:setImage', this);
|
||||
},
|
||||
|
||||
importImage: function() {
|
||||
var data = this.get('header');
|
||||
if (data.attachment_id === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp.ajax.post( 'custom-header-add', {
|
||||
nonce: _wpCustomizeHeader.nonces.add,
|
||||
wp_customize: 'on',
|
||||
theme: api.settings.theme.stylesheet,
|
||||
attachment_id: data.attachment_id
|
||||
} );
|
||||
},
|
||||
|
||||
shouldBeCropped: function() {
|
||||
if (this.get('themeFlexWidth') === true &&
|
||||
this.get('themeFlexHeight') === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeFlexWidth') === true &&
|
||||
this.get('themeHeight') === this.get('imageHeight')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeFlexHeight') === true &&
|
||||
this.get('themeWidth') === this.get('imageWidth')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('themeWidth') === this.get('imageWidth') &&
|
||||
this.get('themeHeight') === this.get('imageHeight')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.get('imageWidth') <= this.get('themeWidth')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceList
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.ChoiceList
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Collection
|
||||
*/
|
||||
api.HeaderTool.ChoiceList = Backbone.Collection.extend({
|
||||
model: api.HeaderTool.ImageModel,
|
||||
|
||||
// Ordered from most recently used to least.
|
||||
comparator: function(model) {
|
||||
return -model.get('header').timestamp;
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''),
|
||||
isRandom = this.isRandomChoice(api.get().header_image);
|
||||
|
||||
// Overridable by an extending class.
|
||||
if (!this.type) {
|
||||
this.type = 'uploaded';
|
||||
}
|
||||
|
||||
// Overridable by an extending class.
|
||||
if (typeof this.data === 'undefined') {
|
||||
this.data = _wpCustomizeHeader.uploads;
|
||||
}
|
||||
|
||||
if (isRandom) {
|
||||
// So that when adding data we don't hide regular images.
|
||||
current = api.get().header_image;
|
||||
}
|
||||
|
||||
this.on('control:setImage', this.setImage, this);
|
||||
this.on('control:removeImage', this.removeImage, this);
|
||||
this.on('add', this.maybeRemoveOldCrop, this);
|
||||
this.on('add', this.maybeAddRandomChoice, this);
|
||||
|
||||
_.each(this.data, function(elt, index) {
|
||||
if (!elt.attachment_id) {
|
||||
elt.defaultName = index;
|
||||
}
|
||||
|
||||
if (typeof elt.timestamp === 'undefined') {
|
||||
elt.timestamp = 0;
|
||||
}
|
||||
|
||||
this.add({
|
||||
header: elt,
|
||||
choice: elt.url.split('/').pop(),
|
||||
selected: current === elt.url.replace(/^https?:\/\//, '')
|
||||
}, { silent: true });
|
||||
}, this);
|
||||
|
||||
if (this.size() > 0) {
|
||||
this.addRandomChoice(current);
|
||||
}
|
||||
},
|
||||
|
||||
maybeRemoveOldCrop: function( model ) {
|
||||
var newID = model.get( 'header' ).attachment_id || false,
|
||||
oldCrop;
|
||||
|
||||
// Bail early if we don't have a new attachment ID.
|
||||
if ( ! newID ) {
|
||||
return;
|
||||
}
|
||||
|
||||
oldCrop = this.find( function( item ) {
|
||||
return ( item.cid !== model.cid && item.get( 'header' ).attachment_id === newID );
|
||||
} );
|
||||
|
||||
// If we found an old crop, remove it from the collection.
|
||||
if ( oldCrop ) {
|
||||
this.remove( oldCrop );
|
||||
}
|
||||
},
|
||||
|
||||
maybeAddRandomChoice: function() {
|
||||
if (this.size() === 1) {
|
||||
this.addRandomChoice();
|
||||
}
|
||||
},
|
||||
|
||||
addRandomChoice: function(initialChoice) {
|
||||
var isRandomSameType = RegExp(this.type).test(initialChoice),
|
||||
randomChoice = 'random-' + this.type + '-image';
|
||||
|
||||
this.add({
|
||||
header: {
|
||||
timestamp: 0,
|
||||
random: randomChoice,
|
||||
width: 245,
|
||||
height: 41
|
||||
},
|
||||
choice: randomChoice,
|
||||
random: true,
|
||||
selected: isRandomSameType
|
||||
});
|
||||
},
|
||||
|
||||
isRandomChoice: function(choice) {
|
||||
return (/^random-(uploaded|default)-image$/).test(choice);
|
||||
},
|
||||
|
||||
shouldHideTitle: function() {
|
||||
return this.size() < 2;
|
||||
},
|
||||
|
||||
setImage: function(model) {
|
||||
this.each(function(m) {
|
||||
m.set('selected', false);
|
||||
});
|
||||
|
||||
if (model) {
|
||||
model.set('selected', true);
|
||||
}
|
||||
},
|
||||
|
||||
removeImage: function() {
|
||||
this.each(function(m) {
|
||||
m.set('selected', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.DefaultsList
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.DefaultsList
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.HeaderTool.ChoiceList
|
||||
* @augments Backbone.Collection
|
||||
*/
|
||||
api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({
|
||||
initialize: function() {
|
||||
this.type = 'default';
|
||||
this.data = _wpCustomizeHeader.defaults;
|
||||
api.HeaderTool.ChoiceList.prototype.initialize.apply(this);
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, window.wp );
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(i){var a=i.customize;a.HeaderTool={},a.HeaderTool.ImageModel=Backbone.Model.extend({defaults:function(){return{header:{attachment_id:0,url:"",timestamp:_.now(),thumbnail_url:""},choice:"",selected:!1,random:!1}},initialize:function(){this.on("hide",this.hide,this)},hide:function(){this.set("choice",""),a("header_image").set("remove-header"),a("header_image_data").set("remove-header")},destroy:function(){var e=this.get("header"),t=a.HeaderTool.currentHeader.get("header").attachment_id;t&&e.attachment_id===t&&a.HeaderTool.currentHeader.trigger("hide"),i.ajax.post("custom-header-remove",{nonce:_wpCustomizeHeader.nonces.remove,wp_customize:"on",theme:a.settings.theme.stylesheet,attachment_id:e.attachment_id}),this.trigger("destroy",this,this.collection)},save:function(){this.get("random")?(a("header_image").set(this.get("header").random),a("header_image_data").set(this.get("header").random)):this.get("header").defaultName?(a("header_image").set(this.get("header").url),a("header_image_data").set(this.get("header").defaultName)):(a("header_image").set(this.get("header").url),a("header_image_data").set(this.get("header"))),a.HeaderTool.combinedList.trigger("control:setImage",this)},importImage:function(){var e=this.get("header");void 0!==e.attachment_id&&i.ajax.post("custom-header-add",{nonce:_wpCustomizeHeader.nonces.add,wp_customize:"on",theme:a.settings.theme.stylesheet,attachment_id:e.attachment_id})},shouldBeCropped:function(){return(!0!==this.get("themeFlexWidth")||!0!==this.get("themeFlexHeight"))&&!(!0===this.get("themeFlexWidth")&&this.get("themeHeight")===this.get("imageHeight")||!0===this.get("themeFlexHeight")&&this.get("themeWidth")===this.get("imageWidth")||this.get("themeWidth")===this.get("imageWidth")&&this.get("themeHeight")===this.get("imageHeight")||this.get("imageWidth")<=this.get("themeWidth"))}}),a.HeaderTool.ChoiceList=Backbone.Collection.extend({model:a.HeaderTool.ImageModel,comparator:function(e){return-e.get("header").timestamp},initialize:function(){var i=a.HeaderTool.currentHeader.get("choice").replace(/^https?:\/\//,""),e=this.isRandomChoice(a.get().header_image);this.type||(this.type="uploaded"),void 0===this.data&&(this.data=_wpCustomizeHeader.uploads),e&&(i=a.get().header_image),this.on("control:setImage",this.setImage,this),this.on("control:removeImage",this.removeImage,this),this.on("add",this.maybeRemoveOldCrop,this),this.on("add",this.maybeAddRandomChoice,this),_.each(this.data,function(e,t){e.attachment_id||(e.defaultName=t),void 0===e.timestamp&&(e.timestamp=0),this.add({header:e,choice:e.url.split("/").pop(),selected:i===e.url.replace(/^https?:\/\//,"")},{silent:!0})},this),0<this.size()&&this.addRandomChoice(i)},maybeRemoveOldCrop:function(t){var e,i=t.get("header").attachment_id||!1;i&&(e=this.find(function(e){return e.cid!==t.cid&&e.get("header").attachment_id===i}))&&this.remove(e)},maybeAddRandomChoice:function(){1===this.size()&&this.addRandomChoice()},addRandomChoice:function(e){var e=RegExp(this.type).test(e),t="random-"+this.type+"-image";this.add({header:{timestamp:0,random:t,width:245,height:41},choice:t,random:!0,selected:e})},isRandomChoice:function(e){return/^random-(uploaded|default)-image$/.test(e)},shouldHideTitle:function(){return this.size()<2},setImage:function(e){this.each(function(e){e.set("selected",!1)}),e&&e.set("selected",!0)},removeImage:function(){this.each(function(e){e.set("selected",!1)})}}),a.HeaderTool.DefaultsList=a.HeaderTool.ChoiceList.extend({initialize:function(){this.type="default",this.data=_wpCustomizeHeader.defaults,a.HeaderTool.ChoiceList.prototype.initialize.apply(this)}})}((jQuery,window.wp));
|
||||
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-preview-nav-menus.js
|
||||
*/
|
||||
|
||||
/* global _wpCustomizePreviewNavMenusExports */
|
||||
|
||||
/** @namespace wp.customize.navMenusPreview */
|
||||
wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( $, _, wp, api ) {
|
||||
'use strict';
|
||||
|
||||
var self = {
|
||||
data: {
|
||||
navMenuInstanceArgs: {}
|
||||
}
|
||||
};
|
||||
if ( 'undefined' !== typeof _wpCustomizePreviewNavMenusExports ) {
|
||||
_.extend( self.data, _wpCustomizePreviewNavMenusExports );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize nav menus preview.
|
||||
*/
|
||||
self.init = function() {
|
||||
var self = this, synced = false;
|
||||
|
||||
/*
|
||||
* Keep track of whether we synced to determine whether or not bindSettingListener
|
||||
* should also initially fire the listener. This initial firing needs to wait until
|
||||
* after all of the settings have been synced from the pane in order to prevent
|
||||
* an infinite selective fallback-refresh. Note that this sync handler will be
|
||||
* added after the sync handler in customize-preview.js, so it will be triggered
|
||||
* after all of the settings are added.
|
||||
*/
|
||||
api.preview.bind( 'sync', function() {
|
||||
synced = true;
|
||||
} );
|
||||
|
||||
if ( api.selectiveRefresh ) {
|
||||
// Listen for changes to settings related to nav menus.
|
||||
api.each( function( setting ) {
|
||||
self.bindSettingListener( setting );
|
||||
} );
|
||||
api.bind( 'add', function( setting ) {
|
||||
|
||||
/*
|
||||
* Handle case where an invalid nav menu item (one for which its associated object has been deleted)
|
||||
* is synced from the controls into the preview. Since invalid nav menu items are filtered out from
|
||||
* being exported to the frontend by the _is_valid_nav_menu_item filter in wp_get_nav_menu_items(),
|
||||
* the customizer controls will have a nav_menu_item setting where the preview will have none, and
|
||||
* this can trigger an infinite fallback refresh when the nav menu item lacks any valid items.
|
||||
*/
|
||||
if ( setting.get() && ! setting.get()._invalid ) {
|
||||
self.bindSettingListener( setting, { fire: synced } );
|
||||
}
|
||||
} );
|
||||
api.bind( 'remove', function( setting ) {
|
||||
self.unbindSettingListener( setting );
|
||||
} );
|
||||
|
||||
/*
|
||||
* Ensure that wp_nav_menu() instances nested inside of other partials
|
||||
* will be recognized as being present on the page.
|
||||
*/
|
||||
api.selectiveRefresh.bind( 'render-partials-response', function( response ) {
|
||||
if ( response.nav_menu_instance_args ) {
|
||||
_.extend( self.data.navMenuInstanceArgs, response.nav_menu_instance_args );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
api.preview.bind( 'active', function() {
|
||||
self.highlightControls();
|
||||
} );
|
||||
};
|
||||
|
||||
if ( api.selectiveRefresh ) {
|
||||
|
||||
/**
|
||||
* Partial representing an invocation of wp_nav_menu().
|
||||
*
|
||||
* @memberOf wp.customize.navMenusPreview
|
||||
* @alias wp.customize.navMenusPreview.NavMenuInstancePartial
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.selectiveRefresh.Partial
|
||||
* @since 4.5.0
|
||||
*/
|
||||
self.NavMenuInstancePartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.navMenusPreview.NavMenuInstancePartial.prototype */{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 4.5.0
|
||||
* @param {string} id - Partial ID.
|
||||
* @param {Object} options
|
||||
* @param {Object} options.params
|
||||
* @param {Object} options.params.navMenuArgs
|
||||
* @param {string} options.params.navMenuArgs.args_hmac
|
||||
* @param {string} [options.params.navMenuArgs.theme_location]
|
||||
* @param {number} [options.params.navMenuArgs.menu]
|
||||
* @param {Object} [options.constructingContainerContext]
|
||||
*/
|
||||
initialize: function( id, options ) {
|
||||
var partial = this, matches, argsHmac;
|
||||
matches = id.match( /^nav_menu_instance\[([0-9a-f]{32})]$/ );
|
||||
if ( ! matches ) {
|
||||
throw new Error( 'Illegal id for nav_menu_instance partial. The key corresponds with the args HMAC.' );
|
||||
}
|
||||
argsHmac = matches[1];
|
||||
|
||||
options = options || {};
|
||||
options.params = _.extend(
|
||||
{
|
||||
selector: '[data-customize-partial-id="' + id + '"]',
|
||||
navMenuArgs: options.constructingContainerContext || {},
|
||||
containerInclusive: true
|
||||
},
|
||||
options.params || {}
|
||||
);
|
||||
api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
|
||||
|
||||
if ( ! _.isObject( partial.params.navMenuArgs ) ) {
|
||||
throw new Error( 'Missing navMenuArgs' );
|
||||
}
|
||||
if ( partial.params.navMenuArgs.args_hmac !== argsHmac ) {
|
||||
throw new Error( 'args_hmac mismatch with id' );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Return whether the setting is related to this partial.
|
||||
*
|
||||
* @since 4.5.0
|
||||
* @param {wp.customize.Value|string} setting - Object or ID.
|
||||
* @param {number|Object|false|null} newValue - New value, or null if the setting was just removed.
|
||||
* @param {number|Object|false|null} oldValue - Old value, or null if the setting was just added.
|
||||
* @return {boolean}
|
||||
*/
|
||||
isRelatedSetting: function( setting, newValue, oldValue ) {
|
||||
var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting, _newValue, _oldValue, urlParser;
|
||||
if ( _.isString( setting ) ) {
|
||||
setting = api( setting );
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent nav_menu_item changes only containing type_label differences triggering a refresh.
|
||||
* These settings in the preview do not include type_label property, and so if one of these
|
||||
* nav_menu_item settings is dirty, after a refresh the nav menu instance would do a selective
|
||||
* refresh immediately because the setting from the pane would have the type_label whereas
|
||||
* the setting in the preview would not, thus triggering a change event. The following
|
||||
* condition short-circuits this unnecessary selective refresh and also prevents an infinite
|
||||
* loop in the case where a nav_menu_instance partial had done a fallback refresh.
|
||||
* @todo Nav menu item settings should not include a type_label property to begin with.
|
||||
*/
|
||||
isNavMenuItemSetting = /^nav_menu_item\[/.test( setting.id );
|
||||
if ( isNavMenuItemSetting && _.isObject( newValue ) && _.isObject( oldValue ) ) {
|
||||
_newValue = _.clone( newValue );
|
||||
_oldValue = _.clone( oldValue );
|
||||
delete _newValue.type_label;
|
||||
delete _oldValue.type_label;
|
||||
|
||||
// Normalize URL scheme when parent frame is HTTPS to prevent selective refresh upon initial page load.
|
||||
if ( 'https' === api.preview.scheme.get() ) {
|
||||
urlParser = document.createElement( 'a' );
|
||||
urlParser.href = _newValue.url;
|
||||
urlParser.protocol = 'https:';
|
||||
_newValue.url = urlParser.href;
|
||||
urlParser.href = _oldValue.url;
|
||||
urlParser.protocol = 'https:';
|
||||
_oldValue.url = urlParser.href;
|
||||
}
|
||||
|
||||
// Prevent original_title differences from causing refreshes if title is present.
|
||||
if ( newValue.title ) {
|
||||
delete _oldValue.original_title;
|
||||
delete _newValue.original_title;
|
||||
}
|
||||
|
||||
if ( _.isEqual( _oldValue, _newValue ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( partial.params.navMenuArgs.theme_location ) {
|
||||
if ( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' === setting.id ) {
|
||||
return true;
|
||||
}
|
||||
navMenuLocationSetting = api( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' );
|
||||
}
|
||||
|
||||
navMenuId = partial.params.navMenuArgs.menu;
|
||||
if ( ! navMenuId && navMenuLocationSetting ) {
|
||||
navMenuId = navMenuLocationSetting();
|
||||
}
|
||||
|
||||
if ( ! navMenuId ) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
( 'nav_menu[' + navMenuId + ']' === setting.id ) ||
|
||||
( isNavMenuItemSetting && (
|
||||
( newValue && newValue.nav_menu_term_id === navMenuId ) ||
|
||||
( oldValue && oldValue.nav_menu_term_id === navMenuId )
|
||||
) )
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Make sure that partial fallback behavior is invoked if there is no associated menu.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
refresh: function() {
|
||||
var partial = this, menuId, deferred = $.Deferred();
|
||||
|
||||
// Make sure the fallback behavior is invoked when the partial is no longer associated with a menu.
|
||||
if ( _.isNumber( partial.params.navMenuArgs.menu ) ) {
|
||||
menuId = partial.params.navMenuArgs.menu;
|
||||
} else if ( partial.params.navMenuArgs.theme_location && api.has( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' ) ) {
|
||||
menuId = api( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' ).get();
|
||||
}
|
||||
if ( ! menuId ) {
|
||||
partial.fallback();
|
||||
deferred.reject();
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
return api.selectiveRefresh.Partial.prototype.refresh.call( partial );
|
||||
},
|
||||
|
||||
/**
|
||||
* Render content.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @param {wp.customize.selectiveRefresh.Placement} placement
|
||||
*/
|
||||
renderContent: function( placement ) {
|
||||
var partial = this, previousContainer = placement.container;
|
||||
|
||||
// Do fallback behavior to refresh preview if menu is now empty.
|
||||
if ( '' === placement.addedContent ) {
|
||||
placement.partial.fallback();
|
||||
}
|
||||
|
||||
if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
|
||||
|
||||
// Trigger deprecated event.
|
||||
$( document ).trigger( 'customize-preview-menu-refreshed', [ {
|
||||
instanceNumber: null, // @deprecated
|
||||
wpNavArgs: placement.context, // @deprecated
|
||||
wpNavMenuArgs: placement.context,
|
||||
oldContainer: previousContainer,
|
||||
newContainer: placement.container
|
||||
} ] );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.selectiveRefresh.partialConstructor.nav_menu_instance = self.NavMenuInstancePartial;
|
||||
|
||||
/**
|
||||
* Request full refresh if there are nav menu instances that lack partials which also match the supplied args.
|
||||
*
|
||||
* @param {Object} navMenuInstanceArgs
|
||||
*/
|
||||
self.handleUnplacedNavMenuInstances = function( navMenuInstanceArgs ) {
|
||||
var unplacedNavMenuInstances;
|
||||
unplacedNavMenuInstances = _.filter( _.values( self.data.navMenuInstanceArgs ), function( args ) {
|
||||
return ! api.selectiveRefresh.partial.has( 'nav_menu_instance[' + args.args_hmac + ']' );
|
||||
} );
|
||||
if ( _.findWhere( unplacedNavMenuInstances, navMenuInstanceArgs ) ) {
|
||||
api.selectiveRefresh.requestFullRefresh();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add change listener for a nav_menu[], nav_menu_item[], or nav_menu_locations[] setting.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {wp.customize.Value} setting
|
||||
* @param {Object} [options]
|
||||
* @param {boolean} options.fire Whether to invoke the callback after binding.
|
||||
* This is used when a dynamic setting is added.
|
||||
* @return {boolean} Whether the setting was bound.
|
||||
*/
|
||||
self.bindSettingListener = function( setting, options ) {
|
||||
var matches;
|
||||
options = options || {};
|
||||
|
||||
matches = setting.id.match( /^nav_menu\[(-?\d+)]$/ );
|
||||
if ( matches ) {
|
||||
setting._navMenuId = parseInt( matches[1], 10 );
|
||||
setting.bind( this.onChangeNavMenuSetting );
|
||||
if ( options.fire ) {
|
||||
this.onChangeNavMenuSetting.call( setting, setting(), false );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
matches = setting.id.match( /^nav_menu_item\[(-?\d+)]$/ );
|
||||
if ( matches ) {
|
||||
setting._navMenuItemId = parseInt( matches[1], 10 );
|
||||
setting.bind( this.onChangeNavMenuItemSetting );
|
||||
if ( options.fire ) {
|
||||
this.onChangeNavMenuItemSetting.call( setting, setting(), false );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
matches = setting.id.match( /^nav_menu_locations\[(.+?)]/ );
|
||||
if ( matches ) {
|
||||
setting._navMenuThemeLocation = matches[1];
|
||||
setting.bind( this.onChangeNavMenuLocationsSetting );
|
||||
if ( options.fire ) {
|
||||
this.onChangeNavMenuLocationsSetting.call( setting, setting(), false );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove change listeners for nav_menu[], nav_menu_item[], or nav_menu_locations[] setting.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {wp.customize.Value} setting
|
||||
*/
|
||||
self.unbindSettingListener = function( setting ) {
|
||||
setting.unbind( this.onChangeNavMenuSetting );
|
||||
setting.unbind( this.onChangeNavMenuItemSetting );
|
||||
setting.unbind( this.onChangeNavMenuLocationsSetting );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle change for nav_menu[] setting for nav menu instances lacking partials.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @this {wp.customize.Value}
|
||||
*/
|
||||
self.onChangeNavMenuSetting = function() {
|
||||
var setting = this;
|
||||
|
||||
self.handleUnplacedNavMenuInstances( {
|
||||
menu: setting._navMenuId
|
||||
} );
|
||||
|
||||
// Ensure all nav menu instances with a theme_location assigned to this menu are handled.
|
||||
api.each( function( otherSetting ) {
|
||||
if ( ! otherSetting._navMenuThemeLocation ) {
|
||||
return;
|
||||
}
|
||||
if ( setting._navMenuId === otherSetting() ) {
|
||||
self.handleUnplacedNavMenuInstances( {
|
||||
theme_location: otherSetting._navMenuThemeLocation
|
||||
} );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle change for nav_menu_item[] setting for nav menu instances lacking partials.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {Object} newItem New value for nav_menu_item[] setting.
|
||||
* @param {Object} oldItem Old value for nav_menu_item[] setting.
|
||||
* @this {wp.customize.Value}
|
||||
*/
|
||||
self.onChangeNavMenuItemSetting = function( newItem, oldItem ) {
|
||||
var item = newItem || oldItem, navMenuSetting;
|
||||
navMenuSetting = api( 'nav_menu[' + String( item.nav_menu_term_id ) + ']' );
|
||||
if ( navMenuSetting ) {
|
||||
self.onChangeNavMenuSetting.call( navMenuSetting );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle change for nav_menu_locations[] setting for nav menu instances lacking partials.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @this {wp.customize.Value}
|
||||
*/
|
||||
self.onChangeNavMenuLocationsSetting = function() {
|
||||
var setting = this, hasNavMenuInstance;
|
||||
self.handleUnplacedNavMenuInstances( {
|
||||
theme_location: setting._navMenuThemeLocation
|
||||
} );
|
||||
|
||||
// If there are no wp_nav_menu() instances that refer to the theme location, do full refresh.
|
||||
hasNavMenuInstance = !! _.findWhere( _.values( self.data.navMenuInstanceArgs ), {
|
||||
theme_location: setting._navMenuThemeLocation
|
||||
} );
|
||||
if ( ! hasNavMenuInstance ) {
|
||||
api.selectiveRefresh.requestFullRefresh();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect nav menu items with their corresponding controls in the pane.
|
||||
*
|
||||
* Setup shift-click on nav menu items which are more granular than the nav menu partial itself.
|
||||
* Also this applies even if a nav menu is not partial-refreshable.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*/
|
||||
self.highlightControls = function() {
|
||||
var selector = '.menu-item';
|
||||
|
||||
// Skip adding highlights if not in the customizer preview iframe.
|
||||
if ( ! api.settings.channel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Focus on the menu item control when shift+clicking the menu item.
|
||||
$( document ).on( 'click', selector, function( e ) {
|
||||
var navMenuItemParts;
|
||||
if ( ! e.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
navMenuItemParts = $( this ).attr( 'class' ).match( /(?:^|\s)menu-item-(-?\d+)(?:\s|$)/ );
|
||||
if ( navMenuItemParts ) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // Make sure a sub-nav menu item will get focused instead of parent items.
|
||||
api.preview.send( 'focus-nav-menu-item-control', parseInt( navMenuItemParts[1], 10 ) );
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
api.bind( 'preview-ready', function() {
|
||||
self.init();
|
||||
} );
|
||||
|
||||
return self;
|
||||
|
||||
}( jQuery, _, wp, wp.customize ) );
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,773 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-preview-widgets.js
|
||||
*/
|
||||
|
||||
/* global _wpWidgetCustomizerPreviewSettings */
|
||||
|
||||
/**
|
||||
* Handles the initialization, refreshing and rendering of widget partials and sidebar widgets.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @namespace wp.customize.widgetsPreview
|
||||
*
|
||||
* @param {jQuery} $ The jQuery object.
|
||||
* @param {Object} _ The utilities library.
|
||||
* @param {Object} wp Current WordPress environment instance.
|
||||
* @param {Object} api Information from the API.
|
||||
*
|
||||
* @return {Object} Widget-related variables.
|
||||
*/
|
||||
wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( $, _, wp, api ) {
|
||||
|
||||
var self;
|
||||
|
||||
self = {
|
||||
renderedSidebars: {},
|
||||
renderedWidgets: {},
|
||||
registeredSidebars: [],
|
||||
registeredWidgets: {},
|
||||
widgetSelectors: [],
|
||||
preview: null,
|
||||
l10n: {
|
||||
widgetTooltip: ''
|
||||
},
|
||||
selectiveRefreshableWidgets: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the widgets preview.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
self.init = function() {
|
||||
var self = this;
|
||||
|
||||
self.preview = api.preview;
|
||||
if ( ! _.isEmpty( self.selectiveRefreshableWidgets ) ) {
|
||||
self.addPartials();
|
||||
}
|
||||
|
||||
self.buildWidgetSelectors();
|
||||
self.highlightControls();
|
||||
|
||||
self.preview.bind( 'highlight-widget', self.highlightWidget );
|
||||
|
||||
api.preview.bind( 'active', function() {
|
||||
self.highlightControls();
|
||||
} );
|
||||
|
||||
/*
|
||||
* Refresh a partial when the controls pane requests it. This is used currently just by the
|
||||
* Gallery widget so that when an attachment's caption is updated in the media modal,
|
||||
* the widget in the preview will then be refreshed to show the change. Normally doing this
|
||||
* would not be necessary because all of the state should be contained inside the changeset,
|
||||
* as everything done in the Customizer should not make a change to the site unless the
|
||||
* changeset itself is published. Attachments are a current exception to this rule.
|
||||
* For a proposal to include attachments in the customized state, see #37887.
|
||||
*/
|
||||
api.preview.bind( 'refresh-widget-partial', function( widgetId ) {
|
||||
var partialId = 'widget[' + widgetId + ']';
|
||||
if ( api.selectiveRefresh.partial.has( partialId ) ) {
|
||||
api.selectiveRefresh.partial( partialId ).refresh();
|
||||
} else if ( self.renderedWidgets[ widgetId ] ) {
|
||||
api.preview.send( 'refresh' ); // Fallback in case theme does not support 'customize-selective-refresh-widgets'.
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
self.WidgetPartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.widgetsPreview.WidgetPartial.prototype */{
|
||||
|
||||
/**
|
||||
* Represents a partial widget instance.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @constructs
|
||||
* @augments wp.customize.selectiveRefresh.Partial
|
||||
*
|
||||
* @alias wp.customize.widgetsPreview.WidgetPartial
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @param {string} id The partial's ID.
|
||||
* @param {Object} options Options used to initialize the partial's
|
||||
* instance.
|
||||
* @param {Object} options.params The options parameters.
|
||||
*/
|
||||
initialize: function( id, options ) {
|
||||
var partial = this, matches;
|
||||
matches = id.match( /^widget\[(.+)]$/ );
|
||||
if ( ! matches ) {
|
||||
throw new Error( 'Illegal id for widget partial.' );
|
||||
}
|
||||
|
||||
partial.widgetId = matches[1];
|
||||
partial.widgetIdParts = self.parseWidgetId( partial.widgetId );
|
||||
options = options || {};
|
||||
options.params = _.extend(
|
||||
{
|
||||
settings: [ self.getWidgetSettingId( partial.widgetId ) ],
|
||||
containerInclusive: true
|
||||
},
|
||||
options.params || {}
|
||||
);
|
||||
|
||||
api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the widget partial.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Promise|void} Either a promise postponing the refresh, or void.
|
||||
*/
|
||||
refresh: function() {
|
||||
var partial = this, refreshDeferred;
|
||||
if ( ! self.selectiveRefreshableWidgets[ partial.widgetIdParts.idBase ] ) {
|
||||
refreshDeferred = $.Deferred();
|
||||
refreshDeferred.reject();
|
||||
partial.fallback();
|
||||
return refreshDeferred.promise();
|
||||
} else {
|
||||
return api.selectiveRefresh.Partial.prototype.refresh.call( partial );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends the widget-updated message to the parent so the spinner will get
|
||||
* removed from the widget control.
|
||||
*
|
||||
* @inheritDoc
|
||||
* @param {wp.customize.selectiveRefresh.Placement} placement The placement
|
||||
* function.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
renderContent: function( placement ) {
|
||||
var partial = this;
|
||||
if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
|
||||
api.preview.send( 'widget-updated', partial.widgetId );
|
||||
api.selectiveRefresh.trigger( 'widget-updated', partial );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.SidebarPartial = api.selectiveRefresh.Partial.extend(/** @lends wp.customize.widgetsPreview.SidebarPartial.prototype */{
|
||||
|
||||
/**
|
||||
* Represents a partial widget area.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.selectiveRefresh.Partial
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
* @alias wp.customize.widgetsPreview.SidebarPartial
|
||||
*
|
||||
* @param {string} id The partial's ID.
|
||||
* @param {Object} options Options used to initialize the partial's instance.
|
||||
* @param {Object} options.params The options parameters.
|
||||
*/
|
||||
initialize: function( id, options ) {
|
||||
var partial = this, matches;
|
||||
matches = id.match( /^sidebar\[(.+)]$/ );
|
||||
if ( ! matches ) {
|
||||
throw new Error( 'Illegal id for sidebar partial.' );
|
||||
}
|
||||
partial.sidebarId = matches[1];
|
||||
|
||||
options = options || {};
|
||||
options.params = _.extend(
|
||||
{
|
||||
settings: [ 'sidebars_widgets[' + partial.sidebarId + ']' ]
|
||||
},
|
||||
options.params || {}
|
||||
);
|
||||
|
||||
api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
|
||||
|
||||
if ( ! partial.params.sidebarArgs ) {
|
||||
throw new Error( 'The sidebarArgs param was not provided.' );
|
||||
}
|
||||
if ( partial.params.settings.length > 1 ) {
|
||||
throw new Error( 'Expected SidebarPartial to only have one associated setting' );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up the partial.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
ready: function() {
|
||||
var sidebarPartial = this;
|
||||
|
||||
// Watch for changes to the sidebar_widgets setting.
|
||||
_.each( sidebarPartial.settings(), function( settingId ) {
|
||||
api( settingId ).bind( _.bind( sidebarPartial.handleSettingChange, sidebarPartial ) );
|
||||
} );
|
||||
|
||||
// Trigger an event for this sidebar being updated whenever a widget inside is rendered.
|
||||
api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
|
||||
var isAssignedWidgetPartial = (
|
||||
placement.partial.extended( self.WidgetPartial ) &&
|
||||
( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), placement.partial.widgetId ) )
|
||||
);
|
||||
if ( isAssignedWidgetPartial ) {
|
||||
api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
|
||||
}
|
||||
} );
|
||||
|
||||
// Make sure that a widget partial has a container in the DOM prior to a refresh.
|
||||
api.bind( 'change', function( widgetSetting ) {
|
||||
var widgetId, parsedId;
|
||||
parsedId = self.parseWidgetSettingId( widgetSetting.id );
|
||||
if ( ! parsedId ) {
|
||||
return;
|
||||
}
|
||||
widgetId = parsedId.idBase;
|
||||
if ( parsedId.number ) {
|
||||
widgetId += '-' + String( parsedId.number );
|
||||
}
|
||||
if ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), widgetId ) ) {
|
||||
sidebarPartial.ensureWidgetPlacementContainers( widgetId );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the before/after boundary nodes for all instances of this sidebar
|
||||
* (usually one).
|
||||
*
|
||||
* Note that TreeWalker is not implemented in IE8.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Array.<{before: Comment, after: Comment, instanceNumber: number}>}
|
||||
* An array with an object for each sidebar instance, containing the
|
||||
* node before and after the sidebar instance and its instance number.
|
||||
*/
|
||||
findDynamicSidebarBoundaryNodes: function() {
|
||||
var partial = this, regExp, boundaryNodes = {}, recursiveCommentTraversal;
|
||||
regExp = /^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/;
|
||||
recursiveCommentTraversal = function( childNodes ) {
|
||||
_.each( childNodes, function( node ) {
|
||||
var matches;
|
||||
if ( 8 === node.nodeType ) {
|
||||
matches = node.nodeValue.match( regExp );
|
||||
if ( ! matches || matches[2] !== partial.sidebarId ) {
|
||||
return;
|
||||
}
|
||||
if ( _.isUndefined( boundaryNodes[ matches[3] ] ) ) {
|
||||
boundaryNodes[ matches[3] ] = {
|
||||
before: null,
|
||||
after: null,
|
||||
instanceNumber: parseInt( matches[3], 10 )
|
||||
};
|
||||
}
|
||||
if ( 'dynamic_sidebar_before' === matches[1] ) {
|
||||
boundaryNodes[ matches[3] ].before = node;
|
||||
} else {
|
||||
boundaryNodes[ matches[3] ].after = node;
|
||||
}
|
||||
} else if ( 1 === node.nodeType ) {
|
||||
recursiveCommentTraversal( node.childNodes );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
recursiveCommentTraversal( document.body.childNodes );
|
||||
return _.values( boundaryNodes );
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the placements for this partial.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Array} An array containing placement objects for each of the
|
||||
* dynamic sidebar boundary nodes.
|
||||
*/
|
||||
placements: function() {
|
||||
var partial = this;
|
||||
return _.map( partial.findDynamicSidebarBoundaryNodes(), function( boundaryNodes ) {
|
||||
return new api.selectiveRefresh.Placement( {
|
||||
partial: partial,
|
||||
container: null,
|
||||
startNode: boundaryNodes.before,
|
||||
endNode: boundaryNodes.after,
|
||||
context: {
|
||||
instanceNumber: boundaryNodes.instanceNumber
|
||||
}
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the list of widget IDs associated with this widget area.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @throws {Error} If there's no settingId.
|
||||
* @throws {Error} If the setting doesn't exist in the API.
|
||||
* @throws {Error} If the API doesn't pass an array of widget IDs.
|
||||
*
|
||||
* @return {Array} A shallow copy of the array containing widget IDs.
|
||||
*/
|
||||
getWidgetIds: function() {
|
||||
var sidebarPartial = this, settingId, widgetIds;
|
||||
settingId = sidebarPartial.settings()[0];
|
||||
if ( ! settingId ) {
|
||||
throw new Error( 'Missing associated setting.' );
|
||||
}
|
||||
if ( ! api.has( settingId ) ) {
|
||||
throw new Error( 'Setting does not exist.' );
|
||||
}
|
||||
widgetIds = api( settingId ).get();
|
||||
if ( ! _.isArray( widgetIds ) ) {
|
||||
throw new Error( 'Expected setting to be array of widget IDs' );
|
||||
}
|
||||
return widgetIds.slice( 0 );
|
||||
},
|
||||
|
||||
/**
|
||||
* Reflows widgets in the sidebar, ensuring they have the proper position in the
|
||||
* DOM.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Array.<wp.customize.selectiveRefresh.Placement>} List of placements
|
||||
* that were reflowed.
|
||||
*/
|
||||
reflowWidgets: function() {
|
||||
var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = [];
|
||||
widgetIds = sidebarPartial.getWidgetIds();
|
||||
sidebarPlacements = sidebarPartial.placements();
|
||||
|
||||
widgetPartials = {};
|
||||
_.each( widgetIds, function( widgetId ) {
|
||||
var widgetPartial = api.selectiveRefresh.partial( 'widget[' + widgetId + ']' );
|
||||
if ( widgetPartial ) {
|
||||
widgetPartials[ widgetId ] = widgetPartial;
|
||||
}
|
||||
} );
|
||||
|
||||
_.each( sidebarPlacements, function( sidebarPlacement ) {
|
||||
var sidebarWidgets = [], needsSort = false, thisPosition, lastPosition = -1;
|
||||
|
||||
// Gather list of widget partial containers in this sidebar, and determine if a sort is needed.
|
||||
_.each( widgetPartials, function( widgetPartial ) {
|
||||
_.each( widgetPartial.placements(), function( widgetPlacement ) {
|
||||
|
||||
if ( sidebarPlacement.context.instanceNumber === widgetPlacement.context.sidebar_instance_number ) {
|
||||
thisPosition = widgetPlacement.container.index();
|
||||
sidebarWidgets.push( {
|
||||
partial: widgetPartial,
|
||||
placement: widgetPlacement,
|
||||
position: thisPosition
|
||||
} );
|
||||
if ( thisPosition < lastPosition ) {
|
||||
needsSort = true;
|
||||
}
|
||||
lastPosition = thisPosition;
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
if ( needsSort ) {
|
||||
_.each( sidebarWidgets, function( sidebarWidget ) {
|
||||
sidebarPlacement.endNode.parentNode.insertBefore(
|
||||
sidebarWidget.placement.container[0],
|
||||
sidebarPlacement.endNode
|
||||
);
|
||||
|
||||
// @todo Rename partial-placement-moved?
|
||||
api.selectiveRefresh.trigger( 'partial-content-moved', sidebarWidget.placement );
|
||||
} );
|
||||
|
||||
sortedSidebarContainers.push( sidebarPlacement );
|
||||
}
|
||||
} );
|
||||
|
||||
if ( sortedSidebarContainers.length > 0 ) {
|
||||
api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
|
||||
}
|
||||
|
||||
return sortedSidebarContainers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes sure there is a widget instance container in this sidebar for the given
|
||||
* widget ID.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {string} widgetId The widget ID.
|
||||
*
|
||||
* @return {wp.customize.selectiveRefresh.Partial} The widget instance partial.
|
||||
*/
|
||||
ensureWidgetPlacementContainers: function( widgetId ) {
|
||||
var sidebarPartial = this, widgetPartial, wasInserted = false, partialId = 'widget[' + widgetId + ']';
|
||||
widgetPartial = api.selectiveRefresh.partial( partialId );
|
||||
if ( ! widgetPartial ) {
|
||||
widgetPartial = new self.WidgetPartial( partialId, {
|
||||
params: {}
|
||||
} );
|
||||
}
|
||||
|
||||
// Make sure that there is a container element for the widget in the sidebar, if at least a placeholder.
|
||||
_.each( sidebarPartial.placements(), function( sidebarPlacement ) {
|
||||
var foundWidgetPlacement, widgetContainerElement;
|
||||
|
||||
foundWidgetPlacement = _.find( widgetPartial.placements(), function( widgetPlacement ) {
|
||||
return ( widgetPlacement.context.sidebar_instance_number === sidebarPlacement.context.instanceNumber );
|
||||
} );
|
||||
if ( foundWidgetPlacement ) {
|
||||
return;
|
||||
}
|
||||
|
||||
widgetContainerElement = $(
|
||||
sidebarPartial.params.sidebarArgs.before_widget.replace( /%1\$s/g, widgetId ).replace( /%2\$s/g, 'widget' ) +
|
||||
sidebarPartial.params.sidebarArgs.after_widget
|
||||
);
|
||||
|
||||
// Handle rare case where before_widget and after_widget are empty.
|
||||
if ( ! widgetContainerElement[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
widgetContainerElement.attr( 'data-customize-partial-id', widgetPartial.id );
|
||||
widgetContainerElement.attr( 'data-customize-partial-type', 'widget' );
|
||||
widgetContainerElement.attr( 'data-customize-widget-id', widgetId );
|
||||
|
||||
/*
|
||||
* Make sure the widget container element has the customize-container context data.
|
||||
* The sidebar_instance_number is used to disambiguate multiple instances of the
|
||||
* same sidebar are rendered onto the template, and so the same widget is embedded
|
||||
* multiple times.
|
||||
*/
|
||||
widgetContainerElement.data( 'customize-partial-placement-context', {
|
||||
'sidebar_id': sidebarPartial.sidebarId,
|
||||
'sidebar_instance_number': sidebarPlacement.context.instanceNumber
|
||||
} );
|
||||
|
||||
sidebarPlacement.endNode.parentNode.insertBefore( widgetContainerElement[0], sidebarPlacement.endNode );
|
||||
wasInserted = true;
|
||||
} );
|
||||
|
||||
api.selectiveRefresh.partial.add( widgetPartial );
|
||||
|
||||
if ( wasInserted ) {
|
||||
sidebarPartial.reflowWidgets();
|
||||
}
|
||||
|
||||
return widgetPartial;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles changes to the sidebars_widgets[] setting.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {Array} newWidgetIds New widget IDs.
|
||||
* @param {Array} oldWidgetIds Old widget IDs.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
handleSettingChange: function( newWidgetIds, oldWidgetIds ) {
|
||||
var sidebarPartial = this, needsRefresh, widgetsRemoved, widgetsAdded, addedWidgetPartials = [];
|
||||
|
||||
needsRefresh = (
|
||||
( oldWidgetIds.length > 0 && 0 === newWidgetIds.length ) ||
|
||||
( newWidgetIds.length > 0 && 0 === oldWidgetIds.length )
|
||||
);
|
||||
if ( needsRefresh ) {
|
||||
sidebarPartial.fallback();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle removal of widgets.
|
||||
widgetsRemoved = _.difference( oldWidgetIds, newWidgetIds );
|
||||
_.each( widgetsRemoved, function( removedWidgetId ) {
|
||||
var widgetPartial = api.selectiveRefresh.partial( 'widget[' + removedWidgetId + ']' );
|
||||
if ( widgetPartial ) {
|
||||
_.each( widgetPartial.placements(), function( placement ) {
|
||||
var isRemoved = (
|
||||
placement.context.sidebar_id === sidebarPartial.sidebarId ||
|
||||
( placement.context.sidebar_args && placement.context.sidebar_args.id === sidebarPartial.sidebarId )
|
||||
);
|
||||
if ( isRemoved ) {
|
||||
placement.container.remove();
|
||||
}
|
||||
} );
|
||||
}
|
||||
delete self.renderedWidgets[ removedWidgetId ];
|
||||
} );
|
||||
|
||||
// Handle insertion of widgets.
|
||||
widgetsAdded = _.difference( newWidgetIds, oldWidgetIds );
|
||||
_.each( widgetsAdded, function( addedWidgetId ) {
|
||||
var widgetPartial = sidebarPartial.ensureWidgetPlacementContainers( addedWidgetId );
|
||||
addedWidgetPartials.push( widgetPartial );
|
||||
self.renderedWidgets[ addedWidgetId ] = true;
|
||||
} );
|
||||
|
||||
_.each( addedWidgetPartials, function( widgetPartial ) {
|
||||
widgetPartial.refresh();
|
||||
} );
|
||||
|
||||
api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the sidebar partial.
|
||||
*
|
||||
* Note that the meat is handled in handleSettingChange because it has the
|
||||
* context of which widgets were removed.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {Promise} A promise postponing the refresh.
|
||||
*/
|
||||
refresh: function() {
|
||||
var partial = this, deferred = $.Deferred();
|
||||
|
||||
deferred.fail( function() {
|
||||
partial.fallback();
|
||||
} );
|
||||
|
||||
if ( 0 === partial.placements().length ) {
|
||||
deferred.reject();
|
||||
} else {
|
||||
_.each( partial.reflowWidgets(), function( sidebarPlacement ) {
|
||||
api.selectiveRefresh.trigger( 'partial-content-rendered', sidebarPlacement );
|
||||
} );
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
});
|
||||
|
||||
api.selectiveRefresh.partialConstructor.sidebar = self.SidebarPartial;
|
||||
api.selectiveRefresh.partialConstructor.widget = self.WidgetPartial;
|
||||
|
||||
/**
|
||||
* Adds partials for the registered widget areas (sidebars).
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
self.addPartials = function() {
|
||||
_.each( self.registeredSidebars, function( registeredSidebar ) {
|
||||
var partial, partialId = 'sidebar[' + registeredSidebar.id + ']';
|
||||
partial = api.selectiveRefresh.partial( partialId );
|
||||
if ( ! partial ) {
|
||||
partial = new self.SidebarPartial( partialId, {
|
||||
params: {
|
||||
sidebarArgs: registeredSidebar
|
||||
}
|
||||
} );
|
||||
api.selectiveRefresh.partial.add( partial );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the selector for the sidebar's widgets based on the registered
|
||||
* sidebar's info.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
self.buildWidgetSelectors = function() {
|
||||
var self = this;
|
||||
|
||||
$.each( self.registeredSidebars, function( i, sidebar ) {
|
||||
var widgetTpl = [
|
||||
sidebar.before_widget,
|
||||
sidebar.before_title,
|
||||
sidebar.after_title,
|
||||
sidebar.after_widget
|
||||
].join( '' ),
|
||||
emptyWidget,
|
||||
widgetSelector,
|
||||
widgetClasses;
|
||||
|
||||
emptyWidget = $( widgetTpl );
|
||||
widgetSelector = emptyWidget.prop( 'tagName' ) || '';
|
||||
widgetClasses = emptyWidget.prop( 'className' ) || '';
|
||||
|
||||
// Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
|
||||
if ( ! widgetClasses ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove class names that incorporate the string formatting placeholders %1$s and %2$s.
|
||||
widgetClasses = widgetClasses.replace( /\S*%[12]\$s\S*/g, '' );
|
||||
widgetClasses = widgetClasses.replace( /^\s+|\s+$/g, '' );
|
||||
if ( widgetClasses ) {
|
||||
widgetSelector += '.' + widgetClasses.split( /\s+/ ).join( '.' );
|
||||
}
|
||||
self.widgetSelectors.push( widgetSelector );
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Highlights the widget on widget updates or widget control mouse overs.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 3.9.0
|
||||
* @param {string} widgetId ID of the widget.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
self.highlightWidget = function( widgetId ) {
|
||||
var $body = $( document.body ),
|
||||
$widget = $( '#' + widgetId );
|
||||
|
||||
$body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
|
||||
|
||||
$widget.addClass( 'widget-customizer-highlighted-widget' );
|
||||
setTimeout( function() {
|
||||
$widget.removeClass( 'widget-customizer-highlighted-widget' );
|
||||
}, 500 );
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a title and highlights widgets on hover. On shift+clicking focuses the
|
||||
* widget control.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
self.highlightControls = function() {
|
||||
var self = this,
|
||||
selector = this.widgetSelectors.join( ',' );
|
||||
|
||||
// Skip adding highlights if not in the customizer preview iframe.
|
||||
if ( ! api.settings.channel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$( selector ).attr( 'title', this.l10n.widgetTooltip );
|
||||
// Highlights widget when entering the widget editor.
|
||||
$( document ).on( 'mouseenter', selector, function() {
|
||||
self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
|
||||
});
|
||||
|
||||
// Open expand the widget control when shift+clicking the widget element.
|
||||
$( document ).on( 'click', selector, function( e ) {
|
||||
if ( ! e.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a widget ID.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {string} widgetId The widget ID.
|
||||
*
|
||||
* @return {{idBase: string, number: number|null}} An object containing the idBase
|
||||
* and number of the parsed widget ID.
|
||||
*/
|
||||
self.parseWidgetId = function( widgetId ) {
|
||||
var matches, parsed = {
|
||||
idBase: '',
|
||||
number: null
|
||||
};
|
||||
|
||||
matches = widgetId.match( /^(.+)-(\d+)$/ );
|
||||
if ( matches ) {
|
||||
parsed.idBase = matches[1];
|
||||
parsed.number = parseInt( matches[2], 10 );
|
||||
} else {
|
||||
parsed.idBase = widgetId; // Likely an old single widget.
|
||||
}
|
||||
|
||||
return parsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a widget setting ID.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {string} settingId Widget setting ID.
|
||||
*
|
||||
* @return {{idBase: string, number: number|null}|null} Either an object containing the idBase
|
||||
* and number of the parsed widget setting ID,
|
||||
* or null.
|
||||
*/
|
||||
self.parseWidgetSettingId = function( settingId ) {
|
||||
var matches, parsed = {
|
||||
idBase: '',
|
||||
number: null
|
||||
};
|
||||
|
||||
matches = settingId.match( /^widget_([^\[]+?)(?:\[(\d+)])?$/ );
|
||||
if ( ! matches ) {
|
||||
return null;
|
||||
}
|
||||
parsed.idBase = matches[1];
|
||||
if ( matches[2] ) {
|
||||
parsed.number = parseInt( matches[2], 10 );
|
||||
}
|
||||
return parsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a widget ID into a Customizer setting ID.
|
||||
*
|
||||
* @memberOf wp.customize.widgetsPreview
|
||||
*
|
||||
* @since 4.5.0
|
||||
*
|
||||
* @param {string} widgetId The widget ID.
|
||||
*
|
||||
* @return {string} The setting ID.
|
||||
*/
|
||||
self.getWidgetSettingId = function( widgetId ) {
|
||||
var parsed = this.parseWidgetId( widgetId ), settingId;
|
||||
|
||||
settingId = 'widget_' + parsed.idBase;
|
||||
if ( parsed.number ) {
|
||||
settingId += '[' + String( parsed.number ) + ']';
|
||||
}
|
||||
|
||||
return settingId;
|
||||
};
|
||||
|
||||
api.bind( 'preview-ready', function() {
|
||||
$.extend( self, _wpWidgetCustomizerPreviewSettings );
|
||||
self.init();
|
||||
});
|
||||
|
||||
return self;
|
||||
})( jQuery, _, wp, wp.customize );
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,899 @@
|
||||
/*
|
||||
* Script run inside a Customizer preview frame.
|
||||
*
|
||||
* @output wp-includes/js/customize-preview.js
|
||||
*/
|
||||
(function( exports, $ ){
|
||||
var api = wp.customize,
|
||||
debounce,
|
||||
currentHistoryState = {};
|
||||
|
||||
/*
|
||||
* Capture the state that is passed into history.replaceState() and history.pushState()
|
||||
* and also which is returned in the popstate event so that when the changeset_uuid
|
||||
* gets updated when transitioning to a new changeset there the current state will
|
||||
* be supplied in the call to history.replaceState().
|
||||
*/
|
||||
( function( history ) {
|
||||
var injectUrlWithState;
|
||||
|
||||
if ( ! history.replaceState ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Amend the supplied URL with the customized state.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access private
|
||||
*
|
||||
* @param {string} url URL.
|
||||
* @return {string} URL with customized state.
|
||||
*/
|
||||
injectUrlWithState = function( url ) {
|
||||
var urlParser, oldQueryParams, newQueryParams;
|
||||
urlParser = document.createElement( 'a' );
|
||||
urlParser.href = url;
|
||||
oldQueryParams = api.utils.parseQueryString( location.search.substr( 1 ) );
|
||||
newQueryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
|
||||
|
||||
newQueryParams.customize_changeset_uuid = oldQueryParams.customize_changeset_uuid;
|
||||
if ( oldQueryParams.customize_autosaved ) {
|
||||
newQueryParams.customize_autosaved = 'on';
|
||||
}
|
||||
if ( oldQueryParams.customize_theme ) {
|
||||
newQueryParams.customize_theme = oldQueryParams.customize_theme;
|
||||
}
|
||||
if ( oldQueryParams.customize_messenger_channel ) {
|
||||
newQueryParams.customize_messenger_channel = oldQueryParams.customize_messenger_channel;
|
||||
}
|
||||
urlParser.search = $.param( newQueryParams );
|
||||
return urlParser.href;
|
||||
};
|
||||
|
||||
history.replaceState = ( function( nativeReplaceState ) {
|
||||
return function historyReplaceState( data, title, url ) {
|
||||
currentHistoryState = data;
|
||||
return nativeReplaceState.call( history, data, title, 'string' === typeof url && url.length > 0 ? injectUrlWithState( url ) : url );
|
||||
};
|
||||
} )( history.replaceState );
|
||||
|
||||
history.pushState = ( function( nativePushState ) {
|
||||
return function historyPushState( data, title, url ) {
|
||||
currentHistoryState = data;
|
||||
return nativePushState.call( history, data, title, 'string' === typeof url && url.length > 0 ? injectUrlWithState( url ) : url );
|
||||
};
|
||||
} )( history.pushState );
|
||||
|
||||
window.addEventListener( 'popstate', function( event ) {
|
||||
currentHistoryState = event.state;
|
||||
} );
|
||||
|
||||
}( history ) );
|
||||
|
||||
/**
|
||||
* Returns a debounced version of the function.
|
||||
*
|
||||
* @todo Require Underscore.js for this file and retire this.
|
||||
*/
|
||||
debounce = function( fn, delay, context ) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var args = arguments;
|
||||
|
||||
context = context || this;
|
||||
|
||||
clearTimeout( timeout );
|
||||
timeout = setTimeout( function() {
|
||||
timeout = null;
|
||||
fn.apply( context, args );
|
||||
}, delay );
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberOf wp.customize
|
||||
* @alias wp.customize.Preview
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Messenger
|
||||
* @augments wp.customize.Class
|
||||
* @mixes wp.customize.Events
|
||||
*/
|
||||
api.Preview = api.Messenger.extend(/** @lends wp.customize.Preview.prototype */{
|
||||
/**
|
||||
* @param {Object} params - Parameters to configure the messenger.
|
||||
* @param {Object} options - Extend any instance parameter or method with this object.
|
||||
*/
|
||||
initialize: function( params, options ) {
|
||||
var preview = this, urlParser = document.createElement( 'a' );
|
||||
|
||||
api.Messenger.prototype.initialize.call( preview, params, options );
|
||||
|
||||
urlParser.href = preview.origin();
|
||||
preview.add( 'scheme', urlParser.protocol.replace( /:$/, '' ) );
|
||||
|
||||
preview.body = $( document.body );
|
||||
preview.window = $( window );
|
||||
|
||||
if ( api.settings.channel ) {
|
||||
|
||||
// If in an iframe, then intercept the link clicks and form submissions.
|
||||
preview.body.on( 'click.preview', 'a', function( event ) {
|
||||
preview.handleLinkClick( event );
|
||||
} );
|
||||
preview.body.on( 'submit.preview', 'form', function( event ) {
|
||||
preview.handleFormSubmit( event );
|
||||
} );
|
||||
|
||||
preview.window.on( 'scroll.preview', debounce( function() {
|
||||
preview.send( 'scroll', preview.window.scrollTop() );
|
||||
}, 200 ) );
|
||||
|
||||
preview.bind( 'scroll', function( distance ) {
|
||||
preview.window.scrollTop( distance );
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle link clicks in preview.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access public
|
||||
*
|
||||
* @param {jQuery.Event} event Event.
|
||||
*/
|
||||
handleLinkClick: function( event ) {
|
||||
var preview = this, link, isInternalJumpLink;
|
||||
link = $( event.target ).closest( 'a' );
|
||||
|
||||
// No-op if the anchor is not a link.
|
||||
if ( _.isUndefined( link.attr( 'href' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow internal jump links and JS links to behave normally without preventing default.
|
||||
isInternalJumpLink = ( '#' === link.attr( 'href' ).substr( 0, 1 ) );
|
||||
if ( isInternalJumpLink || ! /^https?:$/.test( link.prop( 'protocol' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the link is not previewable, prevent the browser from navigating to it.
|
||||
if ( ! api.isLinkPreviewable( link[0] ) ) {
|
||||
wp.a11y.speak( api.settings.l10n.linkUnpreviewable );
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent initiating navigating from click and instead rely on sending url message to pane.
|
||||
event.preventDefault();
|
||||
|
||||
/*
|
||||
* Note the shift key is checked so shift+click on widgets or
|
||||
* nav menu items can just result on focusing on the corresponding
|
||||
* control instead of also navigating to the URL linked to.
|
||||
*/
|
||||
if ( event.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: It's not relevant to send scroll because sending url message will have the same effect.
|
||||
preview.send( 'url', link.prop( 'href' ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle form submit.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access public
|
||||
*
|
||||
* @param {jQuery.Event} event Event.
|
||||
*/
|
||||
handleFormSubmit: function( event ) {
|
||||
var preview = this, urlParser, form;
|
||||
urlParser = document.createElement( 'a' );
|
||||
form = $( event.target );
|
||||
urlParser.href = form.prop( 'action' );
|
||||
|
||||
// If the link is not previewable, prevent the browser from navigating to it.
|
||||
if ( 'GET' !== form.prop( 'method' ).toUpperCase() || ! api.isLinkPreviewable( urlParser ) ) {
|
||||
wp.a11y.speak( api.settings.l10n.formUnpreviewable );
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the default wasn't prevented already (in which case the form
|
||||
* submission is already being handled by JS), and if it has a GET
|
||||
* request method, then take the serialized form data and add it as
|
||||
* a query string to the action URL and send this in a url message
|
||||
* to the customizer pane so that it will be loaded. If the form's
|
||||
* action points to a non-previewable URL, the customizer pane's
|
||||
* previewUrl setter will reject it so that the form submission is
|
||||
* a no-op, which is the same behavior as when clicking a link to an
|
||||
* external site in the preview.
|
||||
*/
|
||||
if ( ! event.isDefaultPrevented() ) {
|
||||
if ( urlParser.search.length > 1 ) {
|
||||
urlParser.search += '&';
|
||||
}
|
||||
urlParser.search += form.serialize();
|
||||
preview.send( 'url', urlParser.href );
|
||||
}
|
||||
|
||||
// Prevent default since navigation should be done via sending url message or via JS submit handler.
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Inject the changeset UUID into links in the document.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
api.addLinkPreviewing = function addLinkPreviewing() {
|
||||
var linkSelectors = 'a[href], area[href]';
|
||||
|
||||
// Inject links into initial document.
|
||||
$( document.body ).find( linkSelectors ).each( function() {
|
||||
api.prepareLinkPreview( this );
|
||||
} );
|
||||
|
||||
// Inject links for new elements added to the page.
|
||||
if ( 'undefined' !== typeof MutationObserver ) {
|
||||
api.mutationObserver = new MutationObserver( function( mutations ) {
|
||||
_.each( mutations, function( mutation ) {
|
||||
$( mutation.target ).find( linkSelectors ).each( function() {
|
||||
api.prepareLinkPreview( this );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
api.mutationObserver.observe( document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
} );
|
||||
} else {
|
||||
|
||||
// If mutation observers aren't available, fallback to just-in-time injection.
|
||||
$( document.documentElement ).on( 'click focus mouseover', linkSelectors, function() {
|
||||
api.prepareLinkPreview( this );
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Should the supplied link is previewable.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access public
|
||||
*
|
||||
* @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
|
||||
* @param {string} element.search Query string.
|
||||
* @param {string} element.pathname Path.
|
||||
* @param {string} element.host Host.
|
||||
* @param {Object} [options]
|
||||
* @param {Object} [options.allowAdminAjax=false] Allow admin-ajax.php requests.
|
||||
* @return {boolean} Is appropriate for changeset link.
|
||||
*/
|
||||
api.isLinkPreviewable = function isLinkPreviewable( element, options ) {
|
||||
var matchesAllowedUrl, parsedAllowedUrl, args, elementHost;
|
||||
|
||||
args = _.extend( {}, { allowAdminAjax: false }, options || {} );
|
||||
|
||||
if ( 'javascript:' === element.protocol ) { // jshint ignore:line
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only web URLs can be previewed.
|
||||
if ( 'https:' !== element.protocol && 'http:' !== element.protocol ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
elementHost = element.host.replace( /:(80|443)$/, '' );
|
||||
parsedAllowedUrl = document.createElement( 'a' );
|
||||
matchesAllowedUrl = ! _.isUndefined( _.find( api.settings.url.allowed, function( allowedUrl ) {
|
||||
parsedAllowedUrl.href = allowedUrl;
|
||||
return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host.replace( /:(80|443)$/, '' ) === elementHost && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
|
||||
} ) );
|
||||
if ( ! matchesAllowedUrl ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip wp login and signup pages.
|
||||
if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow links to admin ajax as faux frontend URLs.
|
||||
if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) ) {
|
||||
return args.allowAdminAjax;
|
||||
}
|
||||
|
||||
// Disallow links to admin, includes, and content.
|
||||
if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject the customize_changeset_uuid query param into links on the frontend.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
*
|
||||
* @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
|
||||
* @param {string} element.search Query string.
|
||||
* @param {string} element.host Host.
|
||||
* @param {string} element.protocol Protocol.
|
||||
* @return {void}
|
||||
*/
|
||||
api.prepareLinkPreview = function prepareLinkPreview( element ) {
|
||||
var queryParams, $element = $( element );
|
||||
|
||||
// Skip elements with no href attribute. Check first to avoid more expensive checks down the road.
|
||||
if ( ! element.hasAttribute( 'href' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip links in admin bar.
|
||||
if ( $element.closest( '#wpadminbar' ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore links with href="#", href="#id", or non-HTTP protocols (e.g. javascript: and mailto:).
|
||||
if ( '#' === $element.attr( 'href' ).substr( 0, 1 ) || ! /^https?:$/.test( element.protocol ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure links in preview use HTTPS if parent frame uses HTTPS.
|
||||
if ( api.settings.channel && 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.host ) ) {
|
||||
element.protocol = 'https:';
|
||||
}
|
||||
|
||||
// Ignore links with class wp-playlist-caption.
|
||||
if ( $element.hasClass( 'wp-playlist-caption' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! api.isLinkPreviewable( element ) ) {
|
||||
|
||||
// Style link as unpreviewable only if previewing in iframe; if previewing on frontend, links will be allowed to work normally.
|
||||
if ( api.settings.channel ) {
|
||||
$element.addClass( 'customize-unpreviewable' );
|
||||
}
|
||||
return;
|
||||
}
|
||||
$element.removeClass( 'customize-unpreviewable' );
|
||||
|
||||
queryParams = api.utils.parseQueryString( element.search.substring( 1 ) );
|
||||
queryParams.customize_changeset_uuid = api.settings.changeset.uuid;
|
||||
if ( api.settings.changeset.autosaved ) {
|
||||
queryParams.customize_autosaved = 'on';
|
||||
}
|
||||
if ( ! api.settings.theme.active ) {
|
||||
queryParams.customize_theme = api.settings.theme.stylesheet;
|
||||
}
|
||||
if ( api.settings.channel ) {
|
||||
queryParams.customize_messenger_channel = api.settings.channel;
|
||||
}
|
||||
element.search = $.param( queryParams );
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject the changeset UUID into Ajax requests.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
api.addRequestPreviewing = function addRequestPreviewing() {
|
||||
|
||||
/**
|
||||
* Rewrite Ajax requests to inject customizer state.
|
||||
*
|
||||
* @param {Object} options Options.
|
||||
* @param {string} options.type Type.
|
||||
* @param {string} options.url URL.
|
||||
* @param {Object} originalOptions Original options.
|
||||
* @param {XMLHttpRequest} xhr XHR.
|
||||
* @return {void}
|
||||
*/
|
||||
var prefilterAjax = function( options, originalOptions, xhr ) {
|
||||
var urlParser, queryParams, requestMethod, dirtyValues = {};
|
||||
urlParser = document.createElement( 'a' );
|
||||
urlParser.href = options.url;
|
||||
|
||||
// Abort if the request is not for this site.
|
||||
if ( ! api.isLinkPreviewable( urlParser, { allowAdminAjax: true } ) ) {
|
||||
return;
|
||||
}
|
||||
queryParams = api.utils.parseQueryString( urlParser.search.substring( 1 ) );
|
||||
|
||||
// Note that _dirty flag will be cleared with changeset updates.
|
||||
api.each( function( setting ) {
|
||||
if ( setting._dirty ) {
|
||||
dirtyValues[ setting.id ] = setting.get();
|
||||
}
|
||||
} );
|
||||
|
||||
if ( ! _.isEmpty( dirtyValues ) ) {
|
||||
requestMethod = options.type.toUpperCase();
|
||||
|
||||
// Override underlying request method to ensure unsaved changes to changeset can be included (force Backbone.emulateHTTP).
|
||||
if ( 'POST' !== requestMethod ) {
|
||||
xhr.setRequestHeader( 'X-HTTP-Method-Override', requestMethod );
|
||||
queryParams._method = requestMethod;
|
||||
options.type = 'POST';
|
||||
}
|
||||
|
||||
// Amend the post data with the customized values.
|
||||
if ( options.data ) {
|
||||
options.data += '&';
|
||||
} else {
|
||||
options.data = '';
|
||||
}
|
||||
options.data += $.param( {
|
||||
customized: JSON.stringify( dirtyValues )
|
||||
} );
|
||||
}
|
||||
|
||||
// Include customized state query params in URL.
|
||||
queryParams.customize_changeset_uuid = api.settings.changeset.uuid;
|
||||
if ( api.settings.changeset.autosaved ) {
|
||||
queryParams.customize_autosaved = 'on';
|
||||
}
|
||||
if ( ! api.settings.theme.active ) {
|
||||
queryParams.customize_theme = api.settings.theme.stylesheet;
|
||||
}
|
||||
|
||||
// Ensure preview nonce is included with every customized request, to allow post data to be read.
|
||||
queryParams.customize_preview_nonce = api.settings.nonce.preview;
|
||||
|
||||
urlParser.search = $.param( queryParams );
|
||||
options.url = urlParser.href;
|
||||
};
|
||||
|
||||
$.ajaxPrefilter( prefilterAjax );
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject changeset UUID into forms, allowing preview to persist through submissions.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
api.addFormPreviewing = function addFormPreviewing() {
|
||||
|
||||
// Inject inputs for forms in initial document.
|
||||
$( document.body ).find( 'form' ).each( function() {
|
||||
api.prepareFormPreview( this );
|
||||
} );
|
||||
|
||||
// Inject inputs for new forms added to the page.
|
||||
if ( 'undefined' !== typeof MutationObserver ) {
|
||||
api.mutationObserver = new MutationObserver( function( mutations ) {
|
||||
_.each( mutations, function( mutation ) {
|
||||
$( mutation.target ).find( 'form' ).each( function() {
|
||||
api.prepareFormPreview( this );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
api.mutationObserver.observe( document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject changeset into form inputs.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
*
|
||||
* @param {HTMLFormElement} form Form.
|
||||
* @return {void}
|
||||
*/
|
||||
api.prepareFormPreview = function prepareFormPreview( form ) {
|
||||
var urlParser, stateParams = {};
|
||||
|
||||
if ( ! form.action ) {
|
||||
form.action = location.href;
|
||||
}
|
||||
|
||||
urlParser = document.createElement( 'a' );
|
||||
urlParser.href = form.action;
|
||||
|
||||
// Make sure forms in preview use HTTPS if parent frame uses HTTPS.
|
||||
if ( api.settings.channel && 'https' === api.preview.scheme.get() && 'http:' === urlParser.protocol && -1 !== api.settings.url.allowedHosts.indexOf( urlParser.host ) ) {
|
||||
urlParser.protocol = 'https:';
|
||||
form.action = urlParser.href;
|
||||
}
|
||||
|
||||
if ( 'GET' !== form.method.toUpperCase() || ! api.isLinkPreviewable( urlParser ) ) {
|
||||
|
||||
// Style form as unpreviewable only if previewing in iframe; if previewing on frontend, all forms will be allowed to work normally.
|
||||
if ( api.settings.channel ) {
|
||||
$( form ).addClass( 'customize-unpreviewable' );
|
||||
}
|
||||
return;
|
||||
}
|
||||
$( form ).removeClass( 'customize-unpreviewable' );
|
||||
|
||||
stateParams.customize_changeset_uuid = api.settings.changeset.uuid;
|
||||
if ( api.settings.changeset.autosaved ) {
|
||||
stateParams.customize_autosaved = 'on';
|
||||
}
|
||||
if ( ! api.settings.theme.active ) {
|
||||
stateParams.customize_theme = api.settings.theme.stylesheet;
|
||||
}
|
||||
if ( api.settings.channel ) {
|
||||
stateParams.customize_messenger_channel = api.settings.channel;
|
||||
}
|
||||
|
||||
_.each( stateParams, function( value, name ) {
|
||||
var input = $( form ).find( 'input[name="' + name + '"]' );
|
||||
if ( input.length ) {
|
||||
input.val( value );
|
||||
} else {
|
||||
$( form ).prepend( $( '<input>', {
|
||||
type: 'hidden',
|
||||
name: name,
|
||||
value: value
|
||||
} ) );
|
||||
}
|
||||
} );
|
||||
|
||||
// Prevent links from breaking out of preview iframe.
|
||||
if ( api.settings.channel ) {
|
||||
form.target = '_self';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Watch current URL and send keep-alive (heartbeat) messages to the parent.
|
||||
*
|
||||
* Keep the customizer pane notified that the preview is still alive
|
||||
* and that the user hasn't navigated to a non-customized URL.
|
||||
*
|
||||
* @since 4.7.0
|
||||
* @access protected
|
||||
*/
|
||||
api.keepAliveCurrentUrl = ( function() {
|
||||
var previousPathName = location.pathname,
|
||||
previousQueryString = location.search.substr( 1 ),
|
||||
previousQueryParams = null,
|
||||
stateQueryParams = [ 'customize_theme', 'customize_changeset_uuid', 'customize_messenger_channel', 'customize_autosaved' ];
|
||||
|
||||
return function keepAliveCurrentUrl() {
|
||||
var urlParser, currentQueryParams;
|
||||
|
||||
// Short-circuit with keep-alive if previous URL is identical (as is normal case).
|
||||
if ( previousQueryString === location.search.substr( 1 ) && previousPathName === location.pathname ) {
|
||||
api.preview.send( 'keep-alive' );
|
||||
return;
|
||||
}
|
||||
|
||||
urlParser = document.createElement( 'a' );
|
||||
if ( null === previousQueryParams ) {
|
||||
urlParser.search = previousQueryString;
|
||||
previousQueryParams = api.utils.parseQueryString( previousQueryString );
|
||||
_.each( stateQueryParams, function( name ) {
|
||||
delete previousQueryParams[ name ];
|
||||
} );
|
||||
}
|
||||
|
||||
// Determine if current URL minus customized state params and URL hash.
|
||||
urlParser.href = location.href;
|
||||
currentQueryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
|
||||
_.each( stateQueryParams, function( name ) {
|
||||
delete currentQueryParams[ name ];
|
||||
} );
|
||||
|
||||
if ( previousPathName !== location.pathname || ! _.isEqual( previousQueryParams, currentQueryParams ) ) {
|
||||
urlParser.search = $.param( currentQueryParams );
|
||||
urlParser.hash = '';
|
||||
api.settings.url.self = urlParser.href;
|
||||
api.preview.send( 'ready', {
|
||||
currentUrl: api.settings.url.self,
|
||||
activePanels: api.settings.activePanels,
|
||||
activeSections: api.settings.activeSections,
|
||||
activeControls: api.settings.activeControls,
|
||||
settingValidities: api.settings.settingValidities
|
||||
} );
|
||||
} else {
|
||||
api.preview.send( 'keep-alive' );
|
||||
}
|
||||
previousQueryParams = currentQueryParams;
|
||||
previousQueryString = location.search.substr( 1 );
|
||||
previousPathName = location.pathname;
|
||||
};
|
||||
} )();
|
||||
|
||||
api.settingPreviewHandlers = {
|
||||
|
||||
/**
|
||||
* Preview changes to custom logo.
|
||||
*
|
||||
* @param {number} attachmentId Attachment ID for custom logo.
|
||||
* @return {void}
|
||||
*/
|
||||
custom_logo: function( attachmentId ) {
|
||||
$( 'body' ).toggleClass( 'wp-custom-logo', !! attachmentId );
|
||||
},
|
||||
|
||||
/**
|
||||
* Preview changes to custom css.
|
||||
*
|
||||
* @param {string} value Custom CSS..
|
||||
* @return {void}
|
||||
*/
|
||||
custom_css: function( value ) {
|
||||
$( '#wp-custom-css' ).text( value );
|
||||
},
|
||||
|
||||
/**
|
||||
* Preview changes to any of the background settings.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
background: function() {
|
||||
var css = '', settings = {};
|
||||
|
||||
_.each( ['color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment'], function( prop ) {
|
||||
settings[ prop ] = api( 'background_' + prop );
|
||||
} );
|
||||
|
||||
/*
|
||||
* The body will support custom backgrounds if either the color or image are set.
|
||||
*
|
||||
* See get_body_class() in /wp-includes/post-template.php
|
||||
*/
|
||||
$( document.body ).toggleClass( 'custom-background', !! ( settings.color() || settings.image() ) );
|
||||
|
||||
if ( settings.color() ) {
|
||||
css += 'background-color: ' + settings.color() + ';';
|
||||
}
|
||||
|
||||
if ( settings.image() ) {
|
||||
css += 'background-image: url("' + settings.image() + '");';
|
||||
css += 'background-size: ' + settings.size() + ';';
|
||||
css += 'background-position: ' + settings.position_x() + ' ' + settings.position_y() + ';';
|
||||
css += 'background-repeat: ' + settings.repeat() + ';';
|
||||
css += 'background-attachment: ' + settings.attachment() + ';';
|
||||
}
|
||||
|
||||
$( '#custom-background-css' ).text( 'body.custom-background { ' + css + ' }' );
|
||||
}
|
||||
};
|
||||
|
||||
$( function() {
|
||||
var bg, setValue, handleUpdatedChangesetUuid;
|
||||
|
||||
api.settings = window._wpCustomizeSettings;
|
||||
if ( ! api.settings ) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.preview = new api.Preview({
|
||||
url: window.location.href,
|
||||
channel: api.settings.channel
|
||||
});
|
||||
|
||||
api.addLinkPreviewing();
|
||||
api.addRequestPreviewing();
|
||||
api.addFormPreviewing();
|
||||
|
||||
/**
|
||||
* Create/update a setting value.
|
||||
*
|
||||
* @param {string} id - Setting ID.
|
||||
* @param {*} value - Setting value.
|
||||
* @param {boolean} [createDirty] - Whether to create a setting as dirty. Defaults to false.
|
||||
*/
|
||||
setValue = function( id, value, createDirty ) {
|
||||
var setting = api( id );
|
||||
if ( setting ) {
|
||||
setting.set( value );
|
||||
} else {
|
||||
createDirty = createDirty || false;
|
||||
setting = api.create( id, value, {
|
||||
id: id
|
||||
} );
|
||||
|
||||
// Mark dynamically-created settings as dirty so they will get posted.
|
||||
if ( createDirty ) {
|
||||
setting._dirty = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
api.preview.bind( 'settings', function( values ) {
|
||||
$.each( values, setValue );
|
||||
});
|
||||
|
||||
api.preview.trigger( 'settings', api.settings.values );
|
||||
|
||||
$.each( api.settings._dirty, function( i, id ) {
|
||||
var setting = api( id );
|
||||
if ( setting ) {
|
||||
setting._dirty = true;
|
||||
}
|
||||
} );
|
||||
|
||||
api.preview.bind( 'setting', function( args ) {
|
||||
var createDirty = true;
|
||||
setValue.apply( null, args.concat( createDirty ) );
|
||||
});
|
||||
|
||||
api.preview.bind( 'sync', function( events ) {
|
||||
|
||||
/*
|
||||
* Delete any settings that already exist locally which haven't been
|
||||
* modified in the controls while the preview was loading. This prevents
|
||||
* situations where the JS value being synced from the pane may differ
|
||||
* from the PHP-sanitized JS value in the preview which causes the
|
||||
* non-sanitized JS value to clobber the PHP-sanitized value. This
|
||||
* is particularly important for selective refresh partials that
|
||||
* have a fallback refresh behavior since infinite refreshing would
|
||||
* result.
|
||||
*/
|
||||
if ( events.settings && events['settings-modified-while-loading'] ) {
|
||||
_.each( _.keys( events.settings ), function( syncedSettingId ) {
|
||||
if ( api.has( syncedSettingId ) && ! events['settings-modified-while-loading'][ syncedSettingId ] ) {
|
||||
delete events.settings[ syncedSettingId ];
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
$.each( events, function( event, args ) {
|
||||
api.preview.trigger( event, args );
|
||||
});
|
||||
api.preview.send( 'synced' );
|
||||
});
|
||||
|
||||
api.preview.bind( 'active', function() {
|
||||
api.preview.send( 'nonce', api.settings.nonce );
|
||||
|
||||
api.preview.send( 'documentTitle', document.title );
|
||||
|
||||
// Send scroll in case of loading via non-refresh.
|
||||
api.preview.send( 'scroll', $( window ).scrollTop() );
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle update to changeset UUID.
|
||||
*
|
||||
* @param {string} uuid - UUID.
|
||||
* @return {void}
|
||||
*/
|
||||
handleUpdatedChangesetUuid = function( uuid ) {
|
||||
api.settings.changeset.uuid = uuid;
|
||||
|
||||
// Update UUIDs in links and forms.
|
||||
$( document.body ).find( 'a[href], area[href]' ).each( function() {
|
||||
api.prepareLinkPreview( this );
|
||||
} );
|
||||
$( document.body ).find( 'form' ).each( function() {
|
||||
api.prepareFormPreview( this );
|
||||
} );
|
||||
|
||||
/*
|
||||
* Replace the UUID in the URL. Note that the wrapped history.replaceState()
|
||||
* will handle injecting the current api.settings.changeset.uuid into the URL,
|
||||
* so this is merely to trigger that logic.
|
||||
*/
|
||||
if ( history.replaceState ) {
|
||||
history.replaceState( currentHistoryState, '', location.href );
|
||||
}
|
||||
};
|
||||
|
||||
api.preview.bind( 'changeset-uuid', handleUpdatedChangesetUuid );
|
||||
|
||||
api.preview.bind( 'saved', function( response ) {
|
||||
if ( response.next_changeset_uuid ) {
|
||||
handleUpdatedChangesetUuid( response.next_changeset_uuid );
|
||||
}
|
||||
api.trigger( 'saved', response );
|
||||
} );
|
||||
|
||||
// Update the URLs to reflect the fact we've started autosaving.
|
||||
api.preview.bind( 'autosaving', function() {
|
||||
if ( api.settings.changeset.autosaved ) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.settings.changeset.autosaved = true; // Start deferring to any autosave once changeset is updated.
|
||||
|
||||
$( document.body ).find( 'a[href], area[href]' ).each( function() {
|
||||
api.prepareLinkPreview( this );
|
||||
} );
|
||||
$( document.body ).find( 'form' ).each( function() {
|
||||
api.prepareFormPreview( this );
|
||||
} );
|
||||
if ( history.replaceState ) {
|
||||
history.replaceState( currentHistoryState, '', location.href );
|
||||
}
|
||||
} );
|
||||
|
||||
/*
|
||||
* Clear dirty flag for settings when saved to changeset so that they
|
||||
* won't be needlessly included in selective refresh or ajax requests.
|
||||
*/
|
||||
api.preview.bind( 'changeset-saved', function( data ) {
|
||||
_.each( data.saved_changeset_values, function( value, settingId ) {
|
||||
var setting = api( settingId );
|
||||
if ( setting && _.isEqual( setting.get(), value ) ) {
|
||||
setting._dirty = false;
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
api.preview.bind( 'nonce-refresh', function( nonce ) {
|
||||
$.extend( api.settings.nonce, nonce );
|
||||
} );
|
||||
|
||||
/*
|
||||
* Send a message to the parent customize frame with a list of which
|
||||
* containers and controls are active.
|
||||
*/
|
||||
api.preview.send( 'ready', {
|
||||
currentUrl: api.settings.url.self,
|
||||
activePanels: api.settings.activePanels,
|
||||
activeSections: api.settings.activeSections,
|
||||
activeControls: api.settings.activeControls,
|
||||
settingValidities: api.settings.settingValidities
|
||||
} );
|
||||
|
||||
// Send ready when URL changes via JS.
|
||||
setInterval( api.keepAliveCurrentUrl, api.settings.timeouts.keepAliveSend );
|
||||
|
||||
// Display a loading indicator when preview is reloading, and remove on failure.
|
||||
api.preview.bind( 'loading-initiated', function () {
|
||||
$( 'body' ).addClass( 'wp-customizer-unloading' );
|
||||
});
|
||||
api.preview.bind( 'loading-failed', function () {
|
||||
$( 'body' ).removeClass( 'wp-customizer-unloading' );
|
||||
});
|
||||
|
||||
/* Custom Backgrounds */
|
||||
bg = $.map( ['color', 'image', 'preset', 'position_x', 'position_y', 'size', 'repeat', 'attachment'], function( prop ) {
|
||||
return 'background_' + prop;
|
||||
} );
|
||||
|
||||
api.when.apply( api, bg ).done( function() {
|
||||
$.each( arguments, function() {
|
||||
this.bind( api.settingPreviewHandlers.background );
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Custom Logo
|
||||
*
|
||||
* Toggle the wp-custom-logo body class when a logo is added or removed.
|
||||
*
|
||||
* @since 4.5.0
|
||||
*/
|
||||
api( 'custom_logo', function ( setting ) {
|
||||
api.settingPreviewHandlers.custom_logo.call( setting, setting.get() );
|
||||
setting.bind( api.settingPreviewHandlers.custom_logo );
|
||||
} );
|
||||
|
||||
api( 'custom_css[' + api.settings.theme.stylesheet + ']', function( setting ) {
|
||||
setting.bind( api.settingPreviewHandlers.custom_css );
|
||||
} );
|
||||
|
||||
api.trigger( 'preview-ready' );
|
||||
});
|
||||
|
||||
})( wp, jQuery );
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @output wp-includes/js/customize-views.js
|
||||
*/
|
||||
|
||||
(function( $, wp, _ ) {
|
||||
|
||||
if ( ! wp || ! wp.customize ) { return; }
|
||||
var api = wp.customize;
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.CurrentView
|
||||
*
|
||||
* Displays the currently selected header image, or a placeholder in lack
|
||||
* thereof.
|
||||
*
|
||||
* Instantiate with model wp.customize.HeaderTool.currentHeader.
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.CurrentView
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.CurrentView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.CurrentView.prototype */{
|
||||
template: wp.template('header-current'),
|
||||
|
||||
initialize: function() {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template(this.model.toJSON()));
|
||||
this.setButtons();
|
||||
return this;
|
||||
},
|
||||
|
||||
setButtons: function() {
|
||||
var elements = $('#customize-control-header_image .actions .remove');
|
||||
if (this.model.get('choice')) {
|
||||
elements.show();
|
||||
} else {
|
||||
elements.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceView
|
||||
*
|
||||
* Represents a choosable header image, be it user-uploaded,
|
||||
* theme-suggested or a special Randomize choice.
|
||||
*
|
||||
* Takes a wp.customize.HeaderTool.ImageModel.
|
||||
*
|
||||
* Manually changes model wp.customize.HeaderTool.currentHeader via the
|
||||
* `select` method.
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.ChoiceView
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.ChoiceView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.ChoiceView.prototype */{
|
||||
template: wp.template('header-choice'),
|
||||
|
||||
className: 'header-view',
|
||||
|
||||
events: {
|
||||
'click .choice,.random': 'select',
|
||||
'click .close': 'removeImage'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
var properties = [
|
||||
this.model.get('header').url,
|
||||
this.model.get('choice')
|
||||
];
|
||||
|
||||
this.listenTo(this.model, 'change:selected', this.toggleSelected);
|
||||
|
||||
if (_.contains(properties, api.get().header_image)) {
|
||||
api.HeaderTool.currentHeader.set(this.extendedModel());
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template(this.extendedModel()));
|
||||
|
||||
this.toggleSelected();
|
||||
return this;
|
||||
},
|
||||
|
||||
toggleSelected: function() {
|
||||
this.$el.toggleClass('selected', this.model.get('selected'));
|
||||
},
|
||||
|
||||
extendedModel: function() {
|
||||
var c = this.model.get('collection');
|
||||
return _.extend(this.model.toJSON(), {
|
||||
type: c.type
|
||||
});
|
||||
},
|
||||
|
||||
select: function() {
|
||||
this.preventJump();
|
||||
this.model.save();
|
||||
api.HeaderTool.currentHeader.set(this.extendedModel());
|
||||
},
|
||||
|
||||
preventJump: function() {
|
||||
var container = $('.wp-full-overlay-sidebar-content'),
|
||||
scroll = container.scrollTop();
|
||||
|
||||
_.defer(function() {
|
||||
container.scrollTop(scroll);
|
||||
});
|
||||
},
|
||||
|
||||
removeImage: function(e) {
|
||||
e.stopPropagation();
|
||||
this.model.destroy();
|
||||
this.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.ChoiceListView
|
||||
*
|
||||
* A container for ChoiceViews. These choices should be of one same type:
|
||||
* user-uploaded headers or theme-defined ones.
|
||||
*
|
||||
* Takes a wp.customize.HeaderTool.ChoiceList.
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.ChoiceListView
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.ChoiceListView = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.ChoiceListView.prototype */{
|
||||
initialize: function() {
|
||||
this.listenTo(this.collection, 'add', this.addOne);
|
||||
this.listenTo(this.collection, 'remove', this.render);
|
||||
this.listenTo(this.collection, 'sort', this.render);
|
||||
this.listenTo(this.collection, 'change', this.toggleList);
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.empty();
|
||||
this.collection.each(this.addOne, this);
|
||||
this.toggleList();
|
||||
},
|
||||
|
||||
addOne: function(choice) {
|
||||
var view;
|
||||
choice.set({ collection: this.collection });
|
||||
view = new api.HeaderTool.ChoiceView({ model: choice });
|
||||
this.$el.append(view.render().el);
|
||||
},
|
||||
|
||||
toggleList: function() {
|
||||
var title = this.$el.parents().prev('.customize-control-title'),
|
||||
randomButton = this.$el.find('.random').parent();
|
||||
if (this.collection.shouldHideTitle()) {
|
||||
title.add(randomButton).hide();
|
||||
} else {
|
||||
title.add(randomButton).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.customize.HeaderTool.CombinedList
|
||||
*
|
||||
* Aggregates wp.customize.HeaderTool.ChoiceList collections (or any
|
||||
* Backbone object, really) and acts as a bus to feed them events.
|
||||
*
|
||||
* @memberOf wp.customize.HeaderTool
|
||||
* @alias wp.customize.HeaderTool.CombinedList
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
*/
|
||||
api.HeaderTool.CombinedList = wp.Backbone.View.extend(/** @lends wp.customize.HeaderTool.CombinedList.prototype */{
|
||||
initialize: function(collections) {
|
||||
this.collections = collections;
|
||||
this.on('all', this.propagate, this);
|
||||
},
|
||||
propagate: function(event, arg) {
|
||||
_.each(this.collections, function(collection) {
|
||||
collection.trigger(event, arg);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, window.wp, _ );
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(i,e,o){var t;e&&e.customize&&((t=e.customize).HeaderTool.CurrentView=e.Backbone.View.extend({template:e.template("header-current"),initialize:function(){this.listenTo(this.model,"change",this.render),this.render()},render:function(){return this.$el.html(this.template(this.model.toJSON())),this.setButtons(),this},setButtons:function(){var e=i("#customize-control-header_image .actions .remove");this.model.get("choice")?e.show():e.hide()}}),t.HeaderTool.ChoiceView=e.Backbone.View.extend({template:e.template("header-choice"),className:"header-view",events:{"click .choice,.random":"select","click .close":"removeImage"},initialize:function(){var e=[this.model.get("header").url,this.model.get("choice")];this.listenTo(this.model,"change:selected",this.toggleSelected),o.contains(e,t.get().header_image)&&t.HeaderTool.currentHeader.set(this.extendedModel())},render:function(){return this.$el.html(this.template(this.extendedModel())),this.toggleSelected(),this},toggleSelected:function(){this.$el.toggleClass("selected",this.model.get("selected"))},extendedModel:function(){var e=this.model.get("collection");return o.extend(this.model.toJSON(),{type:e.type})},select:function(){this.preventJump(),this.model.save(),t.HeaderTool.currentHeader.set(this.extendedModel())},preventJump:function(){var e=i(".wp-full-overlay-sidebar-content"),t=e.scrollTop();o.defer(function(){e.scrollTop(t)})},removeImage:function(e){e.stopPropagation(),this.model.destroy(),this.remove()}}),t.HeaderTool.ChoiceListView=e.Backbone.View.extend({initialize:function(){this.listenTo(this.collection,"add",this.addOne),this.listenTo(this.collection,"remove",this.render),this.listenTo(this.collection,"sort",this.render),this.listenTo(this.collection,"change",this.toggleList),this.render()},render:function(){this.$el.empty(),this.collection.each(this.addOne,this),this.toggleList()},addOne:function(e){e.set({collection:this.collection}),e=new t.HeaderTool.ChoiceView({model:e}),this.$el.append(e.render().el)},toggleList:function(){var e=this.$el.parents().prev(".customize-control-title"),t=this.$el.find(".random").parent();this.collection.shouldHideTitle()?e.add(t).hide():e.add(t).show()}}),t.HeaderTool.CombinedList=e.Backbone.View.extend({initialize:function(e){this.collections=e,this.on("all",this.propagate,this)},propagate:function(t,i){o.each(this.collections,function(e){e.trigger(t,i)})}}))}(jQuery,window.wp,_);
|
||||
@@ -0,0 +1,906 @@
|
||||
/**
|
||||
* Heartbeat API
|
||||
*
|
||||
* Heartbeat is a simple server polling API that sends XHR requests to
|
||||
* the server every 15 - 60 seconds and triggers events (or callbacks) upon
|
||||
* receiving data. Currently these 'ticks' handle transports for post locking,
|
||||
* login-expiration warnings, autosave, and related tasks while a user is logged in.
|
||||
*
|
||||
* Available PHP filters (in ajax-actions.php):
|
||||
* - heartbeat_received
|
||||
* - heartbeat_send
|
||||
* - heartbeat_tick
|
||||
* - heartbeat_nopriv_received
|
||||
* - heartbeat_nopriv_send
|
||||
* - heartbeat_nopriv_tick
|
||||
* @see wp_ajax_nopriv_heartbeat(), wp_ajax_heartbeat()
|
||||
*
|
||||
* Custom jQuery events:
|
||||
* - heartbeat-send
|
||||
* - heartbeat-tick
|
||||
* - heartbeat-error
|
||||
* - heartbeat-connection-lost
|
||||
* - heartbeat-connection-restored
|
||||
* - heartbeat-nonces-expired
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @output wp-includes/js/heartbeat.js
|
||||
*/
|
||||
|
||||
( function( $, window, undefined ) {
|
||||
|
||||
/**
|
||||
* Constructs the Heartbeat API.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @return {Object} An instance of the Heartbeat class.
|
||||
* @constructor
|
||||
*/
|
||||
var Heartbeat = function() {
|
||||
var $document = $(document),
|
||||
settings = {
|
||||
// Suspend/resume.
|
||||
suspend: false,
|
||||
|
||||
// Whether suspending is enabled.
|
||||
suspendEnabled: true,
|
||||
|
||||
// Current screen id, defaults to the JS global 'pagenow' when present
|
||||
// (in the admin) or 'front'.
|
||||
screenId: '',
|
||||
|
||||
// XHR request URL, defaults to the JS global 'ajaxurl' when present.
|
||||
url: '',
|
||||
|
||||
// Timestamp, start of the last connection request.
|
||||
lastTick: 0,
|
||||
|
||||
// Container for the enqueued items.
|
||||
queue: {},
|
||||
|
||||
// Connect interval (in seconds).
|
||||
mainInterval: 60,
|
||||
|
||||
// Used when the interval is set to 5 seconds temporarily.
|
||||
tempInterval: 0,
|
||||
|
||||
// Used when the interval is reset.
|
||||
originalInterval: 0,
|
||||
|
||||
// Used to limit the number of Ajax requests.
|
||||
minimalInterval: 0,
|
||||
|
||||
// Used together with tempInterval.
|
||||
countdown: 0,
|
||||
|
||||
// Whether a connection is currently in progress.
|
||||
connecting: false,
|
||||
|
||||
// Whether a connection error occurred.
|
||||
connectionError: false,
|
||||
|
||||
// Used to track non-critical errors.
|
||||
errorcount: 0,
|
||||
|
||||
// Whether at least one connection has been completed successfully.
|
||||
hasConnected: false,
|
||||
|
||||
// Whether the current browser window is in focus and the user is active.
|
||||
hasFocus: true,
|
||||
|
||||
// Timestamp, last time the user was active. Checked every 30 seconds.
|
||||
userActivity: 0,
|
||||
|
||||
// Flag whether events tracking user activity were set.
|
||||
userActivityEvents: false,
|
||||
|
||||
// Timer that keeps track of how long a user has focus.
|
||||
checkFocusTimer: 0,
|
||||
|
||||
// Timer that keeps track of how long needs to be waited before connecting to
|
||||
// the server again.
|
||||
beatTimer: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets local variables and events, then starts the heartbeat.
|
||||
*
|
||||
* @since 3.8.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function initialize() {
|
||||
var options, hidden, visibilityState, visibilitychange;
|
||||
|
||||
if ( typeof window.pagenow === 'string' ) {
|
||||
settings.screenId = window.pagenow;
|
||||
}
|
||||
|
||||
if ( typeof window.ajaxurl === 'string' ) {
|
||||
settings.url = window.ajaxurl;
|
||||
}
|
||||
|
||||
// Pull in options passed from PHP.
|
||||
if ( typeof window.heartbeatSettings === 'object' ) {
|
||||
options = window.heartbeatSettings;
|
||||
|
||||
// The XHR URL can be passed as option when window.ajaxurl is not set.
|
||||
if ( ! settings.url && options.ajaxurl ) {
|
||||
settings.url = options.ajaxurl;
|
||||
}
|
||||
|
||||
/*
|
||||
* The interval can be from 15 to 120 seconds and can be set temporarily to 5 seconds.
|
||||
* It can be set in the initial options or changed later through JS and/or through PHP.
|
||||
*/
|
||||
if ( options.interval ) {
|
||||
settings.mainInterval = options.interval;
|
||||
|
||||
if ( settings.mainInterval < 15 ) {
|
||||
settings.mainInterval = 15;
|
||||
} else if ( settings.mainInterval > 120 ) {
|
||||
settings.mainInterval = 120;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to limit the number of Ajax requests. Overrides all other intervals
|
||||
* if they are shorter. Needed for some hosts that cannot handle frequent requests
|
||||
* and the user may exceed the allocated server CPU time, etc. The minimal interval
|
||||
* can be up to 600 seconds, however setting it to longer than 120 seconds
|
||||
* will limit or disable some of the functionality (like post locks).
|
||||
* Once set at initialization, minimalInterval cannot be changed/overridden.
|
||||
*/
|
||||
if ( options.minimalInterval ) {
|
||||
options.minimalInterval = parseInt( options.minimalInterval, 10 );
|
||||
settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval : 0;
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) {
|
||||
settings.mainInterval = settings.minimalInterval;
|
||||
}
|
||||
|
||||
// 'screenId' can be added from settings on the front end where the JS global
|
||||
// 'pagenow' is not set.
|
||||
if ( ! settings.screenId ) {
|
||||
settings.screenId = options.screenId || 'front';
|
||||
}
|
||||
|
||||
if ( options.suspension === 'disable' ) {
|
||||
settings.suspendEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to milliseconds.
|
||||
settings.mainInterval = settings.mainInterval * 1000;
|
||||
settings.originalInterval = settings.mainInterval;
|
||||
if ( settings.minimalInterval ) {
|
||||
settings.minimalInterval = settings.minimalInterval * 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the interval to 120 seconds by using the Page Visibility API.
|
||||
* If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the
|
||||
* interval will be increased to 120 seconds after 5 minutes of mouse and keyboard
|
||||
* inactivity.
|
||||
*/
|
||||
if ( typeof document.hidden !== 'undefined' ) {
|
||||
hidden = 'hidden';
|
||||
visibilitychange = 'visibilitychange';
|
||||
visibilityState = 'visibilityState';
|
||||
} else if ( typeof document.msHidden !== 'undefined' ) { // IE10.
|
||||
hidden = 'msHidden';
|
||||
visibilitychange = 'msvisibilitychange';
|
||||
visibilityState = 'msVisibilityState';
|
||||
} else if ( typeof document.webkitHidden !== 'undefined' ) { // Android.
|
||||
hidden = 'webkitHidden';
|
||||
visibilitychange = 'webkitvisibilitychange';
|
||||
visibilityState = 'webkitVisibilityState';
|
||||
}
|
||||
|
||||
if ( hidden ) {
|
||||
if ( document[hidden] ) {
|
||||
settings.hasFocus = false;
|
||||
}
|
||||
|
||||
$document.on( visibilitychange + '.wp-heartbeat', function() {
|
||||
if ( document[visibilityState] === 'hidden' ) {
|
||||
blurred();
|
||||
window.clearInterval( settings.checkFocusTimer );
|
||||
} else {
|
||||
focused();
|
||||
if ( document.hasFocus ) {
|
||||
settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Use document.hasFocus() if available.
|
||||
if ( document.hasFocus ) {
|
||||
settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
|
||||
}
|
||||
|
||||
$(window).on( 'pagehide.wp-heartbeat', function() {
|
||||
// Don't connect anymore.
|
||||
suspend();
|
||||
|
||||
// Abort the last request if not completed.
|
||||
if ( settings.xhr && settings.xhr.readyState !== 4 ) {
|
||||
settings.xhr.abort();
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on(
|
||||
'pageshow.wp-heartbeat',
|
||||
/**
|
||||
* Handles pageshow event, specifically when page navigation is restored from back/forward cache.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* @param {PageTransitionEvent} event.originalEvent
|
||||
*/
|
||||
function ( event ) {
|
||||
if ( event.originalEvent.persisted ) {
|
||||
/*
|
||||
* When page navigation is stored via bfcache (Back/Forward Cache), consider this the same as
|
||||
* if the user had just switched to the tab since the behavior is similar.
|
||||
*/
|
||||
focused();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Check for user activity every 30 seconds.
|
||||
window.setInterval( checkUserActivity, 30000 );
|
||||
|
||||
// Start one tick after DOM ready.
|
||||
$( function() {
|
||||
settings.lastTick = time();
|
||||
scheduleNextTick();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time according to the browser.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {number} Returns the current time.
|
||||
*/
|
||||
function time() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the iframe is from the same origin.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {boolean} Returns whether or not the iframe is from the same origin.
|
||||
*/
|
||||
function isLocalFrame( frame ) {
|
||||
var origin, src = frame.src;
|
||||
|
||||
/*
|
||||
* Need to compare strings as WebKit doesn't throw JS errors when iframes have
|
||||
* different origin. It throws uncatchable exceptions.
|
||||
*/
|
||||
if ( src && /^https?:\/\//.test( src ) ) {
|
||||
origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host;
|
||||
|
||||
if ( src.indexOf( origin ) !== 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ( frame.contentWindow.document ) {
|
||||
return true;
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the document's focus has changed.
|
||||
*
|
||||
* @since 4.1.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function checkFocus() {
|
||||
if ( settings.hasFocus && ! document.hasFocus() ) {
|
||||
blurred();
|
||||
} else if ( ! settings.hasFocus && document.hasFocus() ) {
|
||||
focused();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets error state and fires an event on XHR errors or timeout.
|
||||
*
|
||||
* @since 3.8.0
|
||||
* @access private
|
||||
*
|
||||
* @param {string} error The error type passed from the XHR.
|
||||
* @param {number} status The HTTP status code passed from jqXHR
|
||||
* (200, 404, 500, etc.).
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function setErrorState( error, status ) {
|
||||
var trigger;
|
||||
|
||||
if ( error ) {
|
||||
switch ( error ) {
|
||||
case 'abort':
|
||||
// Do nothing.
|
||||
break;
|
||||
case 'timeout':
|
||||
// No response for 30 seconds.
|
||||
trigger = true;
|
||||
break;
|
||||
case 'error':
|
||||
if ( 503 === status && settings.hasConnected ) {
|
||||
trigger = true;
|
||||
break;
|
||||
}
|
||||
/* falls through */
|
||||
case 'parsererror':
|
||||
case 'empty':
|
||||
case 'unknown':
|
||||
settings.errorcount++;
|
||||
|
||||
if ( settings.errorcount > 2 && settings.hasConnected ) {
|
||||
trigger = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( trigger && ! hasConnectionError() ) {
|
||||
settings.connectionError = true;
|
||||
$document.trigger( 'heartbeat-connection-lost', [error, status] );
|
||||
wp.hooks.doAction( 'heartbeat.connection-lost', error, status );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the error state and fires an event if there is a connection error.
|
||||
*
|
||||
* @since 3.8.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function clearErrorState() {
|
||||
// Has connected successfully.
|
||||
settings.hasConnected = true;
|
||||
|
||||
if ( hasConnectionError() ) {
|
||||
settings.errorcount = 0;
|
||||
settings.connectionError = false;
|
||||
$document.trigger( 'heartbeat-connection-restored' );
|
||||
wp.hooks.doAction( 'heartbeat.connection-restored' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers the data and connects to the server.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function connect() {
|
||||
var ajaxData, heartbeatData;
|
||||
|
||||
// If the connection to the server is slower than the interval,
|
||||
// heartbeat connects as soon as the previous connection's response is received.
|
||||
if ( settings.connecting || settings.suspend ) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings.lastTick = time();
|
||||
|
||||
heartbeatData = $.extend( {}, settings.queue );
|
||||
// Clear the data queue. Anything added after this point will be sent on the next tick.
|
||||
settings.queue = {};
|
||||
|
||||
$document.trigger( 'heartbeat-send', [ heartbeatData ] );
|
||||
wp.hooks.doAction( 'heartbeat.send', heartbeatData );
|
||||
|
||||
ajaxData = {
|
||||
data: heartbeatData,
|
||||
interval: settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000,
|
||||
_nonce: typeof window.heartbeatSettings === 'object' ? window.heartbeatSettings.nonce : '',
|
||||
action: 'heartbeat',
|
||||
screen_id: settings.screenId,
|
||||
has_focus: settings.hasFocus
|
||||
};
|
||||
|
||||
if ( 'customize' === settings.screenId ) {
|
||||
ajaxData.wp_customize = 'on';
|
||||
}
|
||||
|
||||
settings.connecting = true;
|
||||
settings.xhr = $.ajax({
|
||||
url: settings.url,
|
||||
type: 'post',
|
||||
timeout: 30000, // Throw an error if not completed after 30 seconds.
|
||||
data: ajaxData,
|
||||
dataType: 'json'
|
||||
}).always( function() {
|
||||
settings.connecting = false;
|
||||
scheduleNextTick();
|
||||
}).done( function( response, textStatus, jqXHR ) {
|
||||
var newInterval;
|
||||
|
||||
if ( ! response ) {
|
||||
setErrorState( 'empty' );
|
||||
return;
|
||||
}
|
||||
|
||||
clearErrorState();
|
||||
|
||||
if ( response.nonces_expired ) {
|
||||
$document.trigger( 'heartbeat-nonces-expired' );
|
||||
wp.hooks.doAction( 'heartbeat.nonces-expired' );
|
||||
}
|
||||
|
||||
// Change the interval from PHP.
|
||||
if ( response.heartbeat_interval ) {
|
||||
newInterval = response.heartbeat_interval;
|
||||
delete response.heartbeat_interval;
|
||||
}
|
||||
|
||||
// Update the heartbeat nonce if set.
|
||||
if ( response.heartbeat_nonce && typeof window.heartbeatSettings === 'object' ) {
|
||||
window.heartbeatSettings.nonce = response.heartbeat_nonce;
|
||||
delete response.heartbeat_nonce;
|
||||
}
|
||||
|
||||
// Update the Rest API nonce if set and wp-api loaded.
|
||||
if ( response.rest_nonce && typeof window.wpApiSettings === 'object' ) {
|
||||
window.wpApiSettings.nonce = response.rest_nonce;
|
||||
// This nonce is required for api-fetch through heartbeat.tick.
|
||||
// delete response.rest_nonce;
|
||||
}
|
||||
|
||||
$document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] );
|
||||
wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR );
|
||||
|
||||
// Do this last. Can trigger the next XHR if connection time > 5 seconds and newInterval == 'fast'.
|
||||
if ( newInterval ) {
|
||||
interval( newInterval );
|
||||
}
|
||||
}).fail( function( jqXHR, textStatus, error ) {
|
||||
setErrorState( textStatus || 'unknown', jqXHR.status );
|
||||
$document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] );
|
||||
wp.hooks.doAction( 'heartbeat.error', jqXHR, textStatus, error );
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the next connection.
|
||||
*
|
||||
* Fires immediately if the connection time is longer than the interval.
|
||||
*
|
||||
* @since 3.8.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function scheduleNextTick() {
|
||||
var delta = time() - settings.lastTick,
|
||||
interval = settings.mainInterval;
|
||||
|
||||
if ( settings.suspend ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! settings.hasFocus ) {
|
||||
interval = 120000; // 120 seconds. Post locks expire after 150 seconds.
|
||||
} else if ( settings.countdown > 0 && settings.tempInterval ) {
|
||||
interval = settings.tempInterval;
|
||||
settings.countdown--;
|
||||
|
||||
if ( settings.countdown < 1 ) {
|
||||
settings.tempInterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && interval < settings.minimalInterval ) {
|
||||
interval = settings.minimalInterval;
|
||||
}
|
||||
|
||||
window.clearTimeout( settings.beatTimer );
|
||||
|
||||
if ( delta < interval ) {
|
||||
settings.beatTimer = window.setTimeout(
|
||||
function() {
|
||||
connect();
|
||||
},
|
||||
interval - delta
|
||||
);
|
||||
} else {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal state when the browser window becomes hidden or loses focus.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function blurred() {
|
||||
settings.hasFocus = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal state when the browser window becomes visible or is in focus.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function focused() {
|
||||
settings.userActivity = time();
|
||||
|
||||
// Resume if suspended.
|
||||
resume();
|
||||
|
||||
if ( ! settings.hasFocus ) {
|
||||
settings.hasFocus = true;
|
||||
scheduleNextTick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspends connecting.
|
||||
*/
|
||||
function suspend() {
|
||||
settings.suspend = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes connecting.
|
||||
*/
|
||||
function resume() {
|
||||
settings.suspend = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs when the user becomes active after a period of inactivity.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function userIsActive() {
|
||||
settings.userActivityEvents = false;
|
||||
$document.off( '.wp-heartbeat-active' );
|
||||
|
||||
$('iframe').each( function( i, frame ) {
|
||||
if ( isLocalFrame( frame ) ) {
|
||||
$( frame.contentWindow ).off( '.wp-heartbeat-active' );
|
||||
}
|
||||
});
|
||||
|
||||
focused();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for user activity.
|
||||
*
|
||||
* Runs every 30 seconds. Sets 'hasFocus = true' if user is active and the window
|
||||
* is in the background. Sets 'hasFocus = false' if the user has been inactive
|
||||
* (no mouse or keyboard activity) for 5 minutes even when the window has focus.
|
||||
*
|
||||
* @since 3.8.0
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function checkUserActivity() {
|
||||
var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
|
||||
|
||||
// Throttle down when no mouse or keyboard activity for 5 minutes.
|
||||
if ( lastActive > 300000 && settings.hasFocus ) {
|
||||
blurred();
|
||||
}
|
||||
|
||||
// Suspend after 10 minutes of inactivity when suspending is enabled.
|
||||
// Always suspend after 60 minutes of inactivity. This will release the post lock, etc.
|
||||
if ( ( settings.suspendEnabled && lastActive > 600000 ) || lastActive > 3600000 ) {
|
||||
suspend();
|
||||
}
|
||||
|
||||
if ( ! settings.userActivityEvents ) {
|
||||
$document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
|
||||
userIsActive();
|
||||
});
|
||||
|
||||
$('iframe').each( function( i, frame ) {
|
||||
if ( isLocalFrame( frame ) ) {
|
||||
$( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
|
||||
userIsActive();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
settings.userActivityEvents = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods.
|
||||
|
||||
/**
|
||||
* Checks whether the window (or any local iframe in it) has focus, or the user
|
||||
* is active.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @return {boolean} True if the window or the user is active.
|
||||
*/
|
||||
function hasFocus() {
|
||||
return settings.hasFocus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is a connection error.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @return {boolean} True if a connection error was found.
|
||||
*/
|
||||
function hasConnectionError() {
|
||||
return settings.connectionError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects as soon as possible regardless of 'hasFocus' state.
|
||||
*
|
||||
* Will not open two concurrent connections. If a connection is in progress,
|
||||
* will connect again immediately after the current connection completes.
|
||||
*
|
||||
* @since 3.8.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function connectNow() {
|
||||
settings.lastTick = 0;
|
||||
scheduleNextTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables suspending.
|
||||
*
|
||||
* Should be used only when Heartbeat is performing critical tasks like
|
||||
* autosave, post-locking, etc. Using this on many screens may overload
|
||||
* the user's hosting account if several browser windows/tabs are left open
|
||||
* for a long time.
|
||||
*
|
||||
* @since 3.8.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function disableSuspend() {
|
||||
settings.suspendEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets/Sets the interval.
|
||||
*
|
||||
* When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
|
||||
* (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
|
||||
* can be passed as second argument. If the window doesn't have focus,
|
||||
* the interval slows down to 2 minutes.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @param {string|number} speed Interval: 'fast' or 5, 15, 30, 60, 120.
|
||||
* Fast equals 5.
|
||||
* @param {string} ticks Tells how many ticks before the interval reverts
|
||||
* back. Used with speed = 'fast' or 5.
|
||||
*
|
||||
* @return {number} Current interval in seconds.
|
||||
*/
|
||||
function interval( speed, ticks ) {
|
||||
var newInterval,
|
||||
oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
|
||||
|
||||
if ( speed ) {
|
||||
switch ( speed ) {
|
||||
case 'fast':
|
||||
case 5:
|
||||
newInterval = 5000;
|
||||
break;
|
||||
case 15:
|
||||
newInterval = 15000;
|
||||
break;
|
||||
case 30:
|
||||
newInterval = 30000;
|
||||
break;
|
||||
case 60:
|
||||
newInterval = 60000;
|
||||
break;
|
||||
case 120:
|
||||
newInterval = 120000;
|
||||
break;
|
||||
case 'long-polling':
|
||||
// Allow long polling (experimental).
|
||||
settings.mainInterval = 0;
|
||||
return 0;
|
||||
default:
|
||||
newInterval = settings.originalInterval;
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && newInterval < settings.minimalInterval ) {
|
||||
newInterval = settings.minimalInterval;
|
||||
}
|
||||
|
||||
if ( 5000 === newInterval ) {
|
||||
ticks = parseInt( ticks, 10 ) || 30;
|
||||
ticks = ticks < 1 || ticks > 30 ? 30 : ticks;
|
||||
|
||||
settings.countdown = ticks;
|
||||
settings.tempInterval = newInterval;
|
||||
} else {
|
||||
settings.countdown = 0;
|
||||
settings.tempInterval = 0;
|
||||
settings.mainInterval = newInterval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the next connection time if new interval has been set.
|
||||
* Will connect immediately if the time since the last connection
|
||||
* is greater than the new interval.
|
||||
*/
|
||||
if ( newInterval !== oldInterval ) {
|
||||
scheduleNextTick();
|
||||
}
|
||||
}
|
||||
|
||||
return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues data to send with the next XHR.
|
||||
*
|
||||
* As the data is send asynchronously, this function doesn't return the XHR
|
||||
* response. To see the response, use the custom jQuery event 'heartbeat-tick'
|
||||
* on the document, example:
|
||||
* $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) {
|
||||
* // code
|
||||
* });
|
||||
* If the same 'handle' is used more than once, the data is not overwritten when
|
||||
* the third argument is 'true'. Use `wp.heartbeat.isQueued('handle')` to see if
|
||||
* any data is already queued for that handle.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @param {string} handle Unique handle for the data, used in PHP to
|
||||
* receive the data.
|
||||
* @param {*} data The data to send.
|
||||
* @param {boolean} noOverwrite Whether to overwrite existing data in the queue.
|
||||
*
|
||||
* @return {boolean} True if the data was queued.
|
||||
*/
|
||||
function enqueue( handle, data, noOverwrite ) {
|
||||
if ( handle ) {
|
||||
if ( noOverwrite && this.isQueued( handle ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
settings.queue[handle] = data;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if data with a particular handle is queued.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
*
|
||||
* @return {boolean} True if the data is queued with this handle.
|
||||
*/
|
||||
function isQueued( handle ) {
|
||||
if ( handle ) {
|
||||
return settings.queue.hasOwnProperty( handle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes data with a particular handle from the queue.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function dequeue( handle ) {
|
||||
if ( handle ) {
|
||||
delete settings.queue[handle];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data that was enqueued with a particular handle.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @memberOf wp.heartbeat.prototype
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
*
|
||||
* @return {*} The data or undefined.
|
||||
*/
|
||||
function getQueuedItem( handle ) {
|
||||
if ( handle ) {
|
||||
return this.isQueued( handle ) ? settings.queue[handle] : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
||||
// Expose public methods.
|
||||
return {
|
||||
hasFocus: hasFocus,
|
||||
connectNow: connectNow,
|
||||
disableSuspend: disableSuspend,
|
||||
interval: interval,
|
||||
hasConnectionError: hasConnectionError,
|
||||
enqueue: enqueue,
|
||||
dequeue: dequeue,
|
||||
isQueued: isQueued,
|
||||
getQueuedItem: getQueuedItem
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure the global `wp` object exists.
|
||||
*
|
||||
* @namespace wp
|
||||
*/
|
||||
window.wp = window.wp || {};
|
||||
|
||||
/**
|
||||
* Contains the Heartbeat API.
|
||||
*
|
||||
* @namespace wp.heartbeat
|
||||
* @type {Heartbeat}
|
||||
*/
|
||||
window.wp.heartbeat = new Heartbeat();
|
||||
|
||||
}( jQuery, window ));
|
||||
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,169 @@
|
||||
/*!
|
||||
* hoverIntent v1.10.2 // 2020.04.28 // jQuery v1.7.0+
|
||||
* http://briancherne.github.io/jquery-hoverIntent/
|
||||
*
|
||||
* You may use hoverIntent under the terms of the MIT license. Basically that
|
||||
* means you are free to use hoverIntent as long as this header is left intact.
|
||||
* Copyright 2007-2019 Brian Cherne
|
||||
*/
|
||||
|
||||
/**
|
||||
* hoverIntent is similar to jQuery's built-in "hover" method except that
|
||||
* instead of firing the handlerIn function immediately, hoverIntent checks
|
||||
* to see if the user's mouse has slowed down (beneath the sensitivity
|
||||
* threshold) before firing the event. The handlerOut function is only
|
||||
* called after a matching handlerIn.
|
||||
*
|
||||
* // basic usage ... just like .hover()
|
||||
* .hoverIntent( handlerIn, handlerOut )
|
||||
* .hoverIntent( handlerInOut )
|
||||
*
|
||||
* // basic usage ... with event delegation!
|
||||
* .hoverIntent( handlerIn, handlerOut, selector )
|
||||
* .hoverIntent( handlerInOut, selector )
|
||||
*
|
||||
* // using a basic configuration object
|
||||
* .hoverIntent( config )
|
||||
*
|
||||
* @param handlerIn function OR configuration object
|
||||
* @param handlerOut function OR selector for delegation OR undefined
|
||||
* @param selector selector OR undefined
|
||||
* @author Brian Cherne <brian(at)cherne(dot)net>
|
||||
*/
|
||||
|
||||
;(function(factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory(require('jquery'));
|
||||
} else if (jQuery && !jQuery.fn.hoverIntent) {
|
||||
factory(jQuery);
|
||||
}
|
||||
})(function($) {
|
||||
'use strict';
|
||||
|
||||
// default configuration values
|
||||
var _cfg = {
|
||||
interval: 100,
|
||||
sensitivity: 6,
|
||||
timeout: 0
|
||||
};
|
||||
|
||||
// counter used to generate an ID for each instance
|
||||
var INSTANCE_COUNT = 0;
|
||||
|
||||
// current X and Y position of mouse, updated during mousemove tracking (shared across instances)
|
||||
var cX, cY;
|
||||
|
||||
// saves the current pointer position coordinates based on the given mousemove event
|
||||
var track = function(ev) {
|
||||
cX = ev.pageX;
|
||||
cY = ev.pageY;
|
||||
};
|
||||
|
||||
// compares current and previous mouse positions
|
||||
var compare = function(ev,$el,s,cfg) {
|
||||
// compare mouse positions to see if pointer has slowed enough to trigger `over` function
|
||||
if ( Math.sqrt( (s.pX-cX)*(s.pX-cX) + (s.pY-cY)*(s.pY-cY) ) < cfg.sensitivity ) {
|
||||
$el.off(s.event,track);
|
||||
delete s.timeoutId;
|
||||
// set hoverIntent state as active for this element (permits `out` handler to trigger)
|
||||
s.isActive = true;
|
||||
// overwrite old mouseenter event coordinates with most recent pointer position
|
||||
ev.pageX = cX; ev.pageY = cY;
|
||||
// clear coordinate data from state object
|
||||
delete s.pX; delete s.pY;
|
||||
return cfg.over.apply($el[0],[ev]);
|
||||
} else {
|
||||
// set previous coordinates for next comparison
|
||||
s.pX = cX; s.pY = cY;
|
||||
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
|
||||
s.timeoutId = setTimeout( function(){compare(ev, $el, s, cfg);} , cfg.interval );
|
||||
}
|
||||
};
|
||||
|
||||
// triggers given `out` function at configured `timeout` after a mouseleave and clears state
|
||||
var delay = function(ev,$el,s,out) {
|
||||
var data = $el.data('hoverIntent');
|
||||
if (data) {
|
||||
delete data[s.id];
|
||||
}
|
||||
return out.apply($el[0],[ev]);
|
||||
};
|
||||
|
||||
// checks if `value` is a function
|
||||
var isFunction = function(value) {
|
||||
return typeof value === 'function';
|
||||
};
|
||||
|
||||
$.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
|
||||
// instance ID, used as a key to store and retrieve state information on an element
|
||||
var instanceId = INSTANCE_COUNT++;
|
||||
|
||||
// extend the default configuration and parse parameters
|
||||
var cfg = $.extend({}, _cfg);
|
||||
if ( $.isPlainObject(handlerIn) ) {
|
||||
cfg = $.extend(cfg, handlerIn);
|
||||
if ( !isFunction(cfg.out) ) {
|
||||
cfg.out = cfg.over;
|
||||
}
|
||||
} else if ( isFunction(handlerOut) ) {
|
||||
cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
|
||||
} else {
|
||||
cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
|
||||
}
|
||||
|
||||
// A private function for handling mouse 'hovering'
|
||||
var handleHover = function(e) {
|
||||
// cloned event to pass to handlers (copy required for event object to be passed in IE)
|
||||
var ev = $.extend({},e);
|
||||
|
||||
// the current target of the mouse event, wrapped in a jQuery object
|
||||
var $el = $(this);
|
||||
|
||||
// read hoverIntent data from element (or initialize if not present)
|
||||
var hoverIntentData = $el.data('hoverIntent');
|
||||
if (!hoverIntentData) { $el.data('hoverIntent', (hoverIntentData = {})); }
|
||||
|
||||
// read per-instance state from element (or initialize if not present)
|
||||
var state = hoverIntentData[instanceId];
|
||||
if (!state) { hoverIntentData[instanceId] = state = { id: instanceId }; }
|
||||
|
||||
// state properties:
|
||||
// id = instance ID, used to clean up data
|
||||
// timeoutId = timeout ID, reused for tracking mouse position and delaying "out" handler
|
||||
// isActive = plugin state, true after `over` is called just until `out` is called
|
||||
// pX, pY = previously-measured pointer coordinates, updated at each polling interval
|
||||
// event = string representing the namespaced event used for mouse tracking
|
||||
|
||||
// clear any existing timeout
|
||||
if (state.timeoutId) { state.timeoutId = clearTimeout(state.timeoutId); }
|
||||
|
||||
// namespaced event used to register and unregister mousemove tracking
|
||||
var mousemove = state.event = 'mousemove.hoverIntent.hoverIntent'+instanceId;
|
||||
|
||||
// handle the event, based on its type
|
||||
if (e.type === 'mouseenter') {
|
||||
// do nothing if already active
|
||||
if (state.isActive) { return; }
|
||||
// set "previous" X and Y position based on initial entry point
|
||||
state.pX = ev.pageX; state.pY = ev.pageY;
|
||||
// update "current" X and Y position based on mousemove
|
||||
$el.off(mousemove,track).on(mousemove,track);
|
||||
// start polling interval (self-calling timeout) to compare mouse coordinates over time
|
||||
state.timeoutId = setTimeout( function(){compare(ev,$el,state,cfg);} , cfg.interval );
|
||||
} else { // "mouseleave"
|
||||
// do nothing if not already active
|
||||
if (!state.isActive) { return; }
|
||||
// unbind expensive mousemove event
|
||||
$el.off(mousemove,track);
|
||||
// if hoverIntent state is true, then call the mouseOut function after the specified delay
|
||||
state.timeoutId = setTimeout( function(){delay(ev,$el,state,cfg.out);} , cfg.timeout );
|
||||
}
|
||||
};
|
||||
|
||||
// listen for mouseenter and mouseleave
|
||||
return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
|
||||
};
|
||||
});
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=e(require("jquery")):jQuery&&!jQuery.fn.hoverIntent&&e(jQuery)}(function(f){"use strict";function u(e){return"function"==typeof e}var i,r,v={interval:100,sensitivity:6,timeout:0},s=0,a=function(e){i=e.pageX,r=e.pageY},p=function(e,t,n,o){if(Math.sqrt((n.pX-i)*(n.pX-i)+(n.pY-r)*(n.pY-r))<o.sensitivity)return t.off(n.event,a),delete n.timeoutId,n.isActive=!0,e.pageX=i,e.pageY=r,delete n.pX,delete n.pY,o.over.apply(t[0],[e]);n.pX=i,n.pY=r,n.timeoutId=setTimeout(function(){p(e,t,n,o)},o.interval)};f.fn.hoverIntent=function(e,t,n){function o(e){var u=f.extend({},e),r=f(this),v=((t=r.data("hoverIntent"))||r.data("hoverIntent",t={}),t[i]),t=(v||(t[i]=v={id:i}),v.timeoutId&&(v.timeoutId=clearTimeout(v.timeoutId)),v.event="mousemove.hoverIntent.hoverIntent"+i);"mouseenter"===e.type?v.isActive||(v.pX=u.pageX,v.pY=u.pageY,r.off(t,a).on(t,a),v.timeoutId=setTimeout(function(){p(u,r,v,d)},d.interval)):v.isActive&&(r.off(t,a),v.timeoutId=setTimeout(function(){var e,t,n,o,i;e=u,t=r,n=v,o=d.out,(i=t.data("hoverIntent"))&&delete i[n.id],o.apply(t[0],[e])},d.timeout))}var i=s++,d=f.extend({},v);f.isPlainObject(e)?(d=f.extend(d,e),u(d.out)||(d.out=d.over)):d=u(t)?f.extend(d,{over:e,out:t,selector:n}):f.extend(d,{over:e,out:e,selector:t});return this.on({"mouseenter.hoverIntent":o,"mouseleave.hoverIntent":o},d.selector)}});
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! This file is auto-generated */
|
||||
!function(e,t){if("function"==typeof define&&define.amd)define("hoverintent",["module"],t);else if("undefined"!=typeof exports)t(module);else{var n={exports:{}};t(n),e.hoverintent=n.exports}}(this,function(e){"use strict";var t=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e};e.exports=function(e,n,o){function i(e,t){return y&&(y=clearTimeout(y)),b=0,p?void 0:o.call(e,t)}function r(e){m=e.clientX,d=e.clientY}function u(e,t){if(y&&(y=clearTimeout(y)),Math.abs(h-m)+Math.abs(E-d)<x.sensitivity)return b=1,p?void 0:n.call(e,t);h=m,E=d,y=setTimeout(function(){u(e,t)},x.interval)}function s(t){return L=!0,y&&(y=clearTimeout(y)),e.removeEventListener("mousemove",r,!1),1!==b&&(h=t.clientX,E=t.clientY,e.addEventListener("mousemove",r,!1),y=setTimeout(function(){u(e,t)},x.interval)),this}function c(t){return L=!1,y&&(y=clearTimeout(y)),e.removeEventListener("mousemove",r,!1),1===b&&(y=setTimeout(function(){i(e,t)},x.timeout)),this}function v(t){L||(p=!0,n.call(e,t))}function a(t){!L&&p&&(p=!1,o.call(e,t))}function f(){e.addEventListener("focus",v,!1),e.addEventListener("blur",a,!1)}function l(){e.removeEventListener("focus",v,!1),e.removeEventListener("blur",a,!1)}var m,d,h,E,L=!1,p=!1,T={},b=0,y=0,x={sensitivity:7,interval:100,timeout:0,handleFocus:!1};return T.options=function(e){var n=e.handleFocus!==x.handleFocus;return x=t({},x,e),n&&(x.handleFocus?f():l()),T},T.remove=function(){e&&(e.removeEventListener("mouseover",s,!1),e.removeEventListener("mouseout",c,!1),l())},e&&(e.addEventListener("mouseover",s,!1),e.addEventListener("mouseout",c,!1)),T}});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*! This file is auto-generated */
|
||||
/*!
|
||||
* imagesLoaded PACKAGED v5.0.0
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
!function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},s=i[t]=i[t]||[];return s.includes(e)||s.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let s=i.indexOf(e);return-1!=s&&i.splice(s,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let s=this._onceEvents&&this._onceEvents[t];for(let n of i){s&&s[n]&&(this.off(t,n),delete s[n]),n.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})),
|
||||
/*!
|
||||
* imagesLoaded v5.0.0
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){let i=t.jQuery,s=t.console;function n(t,e,o){if(!(this instanceof n))return new n(t,e,o);let r=t;var h;("string"==typeof t&&(r=document.querySelectorAll(t)),r)?(this.elements=(h=r,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?[...h]:[h]),this.options={},"function"==typeof e?o=e:Object.assign(this.options,e),o&&this.on("always",o),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):s.error(`Bad element for imagesLoaded ${r||t}`)}n.prototype=Object.create(e.prototype),n.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)};const o=[1,9,11];n.prototype.addElementImages=function(t){"IMG"===t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);let{nodeType:e}=t;if(!e||!o.includes(e))return;let i=t.querySelectorAll("img");for(let t of i)this.addImage(t);if("string"==typeof this.options.background){let e=t.querySelectorAll(this.options.background);for(let t of e)this.addElementBackgroundImages(t)}};const r=/url\((['"])?(.*?)\1\)/gi;function h(t){this.img=t}function d(t,e){this.url=t,this.element=e,this.img=new Image}return n.prototype.addElementBackgroundImages=function(t){let e=getComputedStyle(t);if(!e)return;let i=r.exec(e.backgroundImage);for(;null!==i;){let s=i&&i[2];s&&this.addBackground(s,t),i=r.exec(e.backgroundImage)}},n.prototype.addImage=function(t){let e=new h(t);this.images.push(e)},n.prototype.addBackground=function(t,e){let i=new d(t,e);this.images.push(i)},n.prototype.check=function(){if(this.progressedCount=0,this.hasAnyBroken=!1,!this.images.length)return void this.complete();let t=(t,e,i)=>{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n}));
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 178 B |
Binary file not shown.
|
After Width: | Height: | Size: 178 B |
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* imgAreaSelect animated border style
|
||||
*/
|
||||
|
||||
.imgareaselect-border1 {
|
||||
background: url(border-anim-v.gif) repeat-y left top;
|
||||
}
|
||||
|
||||
.imgareaselect-border2 {
|
||||
background: url(border-anim-h.gif) repeat-x left top;
|
||||
}
|
||||
|
||||
.imgareaselect-border3 {
|
||||
background: url(border-anim-v.gif) repeat-y right top;
|
||||
}
|
||||
|
||||
.imgareaselect-border4 {
|
||||
background: url(border-anim-h.gif) repeat-x left bottom;
|
||||
}
|
||||
|
||||
.imgareaselect-border1, .imgareaselect-border2,
|
||||
.imgareaselect-border3, .imgareaselect-border4 {
|
||||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.imgareaselect-handle {
|
||||
background-color: #fff;
|
||||
border: solid 1px #000;
|
||||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.imgareaselect-outer {
|
||||
background-color: #000;
|
||||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.imgareaselect-selection {
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 323 B |
@@ -0,0 +1,2 @@
|
||||
/* jquery.Jcrop.min.css v0.9.15 (build:20180819) */
|
||||
.jcrop-holder{direction:ltr;text-align:left;-ms-touch-action:none}.jcrop-hline,.jcrop-vline{background:#fff url(Jcrop.gif);font-size:0;position:absolute}.jcrop-vline{height:100%;width:1px!important}.jcrop-vline.right{right:0}.jcrop-hline{height:1px!important;width:100%}.jcrop-hline.bottom{bottom:0}.jcrop-tracker{height:100%;width:100%;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none}.jcrop-handle{background-color:#333;border:1px #eee solid;width:7px;height:7px;font-size:1px}.jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0}.jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px}.jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%}.jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%}.jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0}.jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0}.jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0}.jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px}.jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%}.jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px}.jcrop-dragbar.ord-n{margin-top:-4px}.jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px}.jcrop-dragbar.ord-e{margin-right:-4px;right:0}.jcrop-dragbar.ord-w{margin-left:-4px}.jcrop-light .jcrop-hline,.jcrop-light .jcrop-vline{background:#fff;filter:alpha(opacity=70)!important;opacity:.7!important}.jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#fff;border-radius:3px}.jcrop-dark .jcrop-hline,.jcrop-dark .jcrop-vline{background:#000;filter:alpha(opacity=70)!important;opacity:.7!important}.jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#fff;border-color:#000;border-radius:3px}.solid-line .jcrop-hline,.solid-line .jcrop-vline{background:#fff}.jcrop-holder img,img.jcrop-preview{max-width:none}
|
||||
File diff suppressed because one or more lines are too long
+1018
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,134 @@
|
||||
/******************************************************************************************************************************
|
||||
|
||||
* @ Original idea by by Binny V A, Original version: 2.00.A
|
||||
* @ http://www.openjs.com/scripts/events/keyboard_shortcuts/
|
||||
* @ Original License : BSD
|
||||
|
||||
* @ jQuery Plugin by Tzury Bar Yochay
|
||||
mail: tzury.by@gmail.com
|
||||
blog: evalinux.wordpress.com
|
||||
face: facebook.com/profile.php?id=513676303
|
||||
|
||||
(c) Copyrights 2007
|
||||
|
||||
* @ jQuery Plugin version Beta (0.0.2)
|
||||
* @ License: jQuery-License.
|
||||
|
||||
TODO:
|
||||
add queue support (as in gmail) e.g. 'x' then 'y', etc.
|
||||
add mouse + mouse wheel events.
|
||||
|
||||
USAGE:
|
||||
$.hotkeys.add('Ctrl+c', function(){ alert('copy anyone?');});
|
||||
$.hotkeys.add('Ctrl+c', {target:'div#editor', type:'keyup', propagate: true},function(){ alert('copy anyone?');});>
|
||||
$.hotkeys.remove('Ctrl+c');
|
||||
$.hotkeys.remove('Ctrl+c', {target:'div#editor', type:'keypress'});
|
||||
|
||||
******************************************************************************************************************************/
|
||||
(function (jQuery){
|
||||
this.version = '(beta)(0.0.3)';
|
||||
this.all = {};
|
||||
this.special_keys = {
|
||||
27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', 20: 'capslock',
|
||||
144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',35:'end', 33: 'pageup',
|
||||
34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', 112:'f1',113:'f2', 114:'f3',
|
||||
115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', 120:'f9', 121:'f10', 122:'f11', 123:'f12'};
|
||||
|
||||
this.shift_nums = { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&",
|
||||
"8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<",
|
||||
".":">", "/":"?", "\\":"|" };
|
||||
|
||||
this.add = function(combi, options, callback) {
|
||||
if ( typeof options === 'function' ){
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
var opt = {},
|
||||
defaults = {type: 'keydown', propagate: false, disableInInput: false, target: jQuery('html')[0]},
|
||||
that = this;
|
||||
opt = jQuery.extend( opt , defaults, options || {} );
|
||||
combi = combi.toLowerCase();
|
||||
|
||||
// inspect if keystroke matches
|
||||
var inspector = function(event) {
|
||||
// WP: not needed with newer jQuery
|
||||
// event = jQuery.event.fix(event); // jQuery event normalization.
|
||||
var element = event.target;
|
||||
// @ TextNode -> nodeType == 3
|
||||
// WP: not needed with newer jQuery
|
||||
// element = (element.nodeType==3) ? element.parentNode : element;
|
||||
|
||||
if ( opt['disableInInput'] ) { // Disable shortcut keys in Input, Textarea fields
|
||||
var target = jQuery(element);
|
||||
|
||||
if ( ( target.is('input') || target.is('textarea') ) &&
|
||||
( ! opt.noDisable || ! target.is( opt.noDisable ) ) ) {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
var code = event.which,
|
||||
type = event.type,
|
||||
character = String.fromCharCode(code).toLowerCase(),
|
||||
special = that.special_keys[code],
|
||||
shift = event.shiftKey,
|
||||
ctrl = event.ctrlKey,
|
||||
alt= event.altKey,
|
||||
meta = event.metaKey,
|
||||
propagate = true, // default behaivour
|
||||
mapPoint = null;
|
||||
|
||||
// in opera + safari, the event.target is unpredictable.
|
||||
// for example: 'keydown' might be associated with HtmlBodyElement
|
||||
// or the element where you last clicked with your mouse.
|
||||
// WP: needed for all browsers
|
||||
// if (jQuery.browser.opera || jQuery.browser.safari){
|
||||
while (!that.all[element] && element.parentNode){
|
||||
element = element.parentNode;
|
||||
}
|
||||
// }
|
||||
var cbMap = that.all[element].events[type].callbackMap;
|
||||
if(!shift && !ctrl && !alt && !meta) { // No Modifiers
|
||||
mapPoint = cbMap[special] || cbMap[character]
|
||||
}
|
||||
// deals with combinaitons (alt|ctrl|shift+anything)
|
||||
else{
|
||||
var modif = '';
|
||||
if(alt) modif +='alt+';
|
||||
if(ctrl) modif+= 'ctrl+';
|
||||
if(shift) modif += 'shift+';
|
||||
if(meta) modif += 'meta+';
|
||||
// modifiers + special keys or modifiers + characters or modifiers + shift characters
|
||||
mapPoint = cbMap[modif+special] || cbMap[modif+character] || cbMap[modif+that.shift_nums[character]]
|
||||
}
|
||||
if (mapPoint){
|
||||
mapPoint.cb(event);
|
||||
if(!mapPoint.propagate) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
// first hook for this element
|
||||
if (!this.all[opt.target]){
|
||||
this.all[opt.target] = {events:{}};
|
||||
}
|
||||
if (!this.all[opt.target].events[opt.type]){
|
||||
this.all[opt.target].events[opt.type] = {callbackMap: {}}
|
||||
jQuery.event.add(opt.target, opt.type, inspector);
|
||||
}
|
||||
this.all[opt.target].events[opt.type].callbackMap[combi] = {cb: callback, propagate:opt.propagate};
|
||||
return jQuery;
|
||||
};
|
||||
this.remove = function(exp, opt) {
|
||||
opt = opt || {};
|
||||
target = opt.target || jQuery('html')[0];
|
||||
type = opt.type || 'keydown';
|
||||
exp = exp.toLowerCase();
|
||||
delete this.all[target].events[type].callbackMap[exp]
|
||||
return jQuery;
|
||||
};
|
||||
jQuery.hotkeys = this;
|
||||
return jQuery;
|
||||
})(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
(function(a){this.version="(beta)(0.0.3)";this.all={};this.special_keys={27:"esc",9:"tab",32:"space",13:"return",8:"backspace",145:"scroll",20:"capslock",144:"numlock",19:"pause",45:"insert",36:"home",46:"del",35:"end",33:"pageup",34:"pagedown",37:"left",38:"up",39:"right",40:"down",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12"};this.shift_nums={"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":":","'":'"',",":"<",".":">","/":"?","\\":"|"};this.add=function(c,b,h){if(a.isFunction(b)){h=b;b={}}var d={},f={type:"keydown",propagate:false,disableInInput:false,target:a("html")[0]},e=this;d=a.extend(d,f,b||{});c=c.toLowerCase();var g=function(j){var o=j.target;if(d.disableInInput){var s=a(o);if(s.is("input")||s.is("textarea")){return}}var l=j.which,u=j.type,r=String.fromCharCode(l).toLowerCase(),t=e.special_keys[l],m=j.shiftKey,i=j.ctrlKey,p=j.altKey,w=j.metaKey,q=true,k=null;while(!e.all[o]&&o.parentNode){o=o.parentNode}var v=e.all[o].events[u].callbackMap;if(!m&&!i&&!p&&!w){k=v[t]||v[r]}else{var n="";if(p){n+="alt+"}if(i){n+="ctrl+"}if(m){n+="shift+"}if(w){n+="meta+"}k=v[n+t]||v[n+r]||v[n+e.shift_nums[r]]}if(k){k.cb(j);if(!k.propagate){j.stopPropagation();j.preventDefault();return false}}};if(!this.all[d.target]){this.all[d.target]={events:{}}}if(!this.all[d.target].events[d.type]){this.all[d.target].events[d.type]={callbackMap:{}};a.event.add(d.target,d.type,g)}this.all[d.target].events[d.type].callbackMap[c]={cb:h,propagate:d.propagate};return a};this.remove=function(c,b){b=b||{};target=b.target||a("html")[0];type=b.type||"keydown";c=c.toLowerCase();delete this.all[target].events[type].callbackMap[c];return a};a.hotkeys=this;return a})(jQuery);
|
||||
+10717
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* Masonry v2 shim
|
||||
* to maintain backwards compatibility
|
||||
* as of Masonry v3.1.2
|
||||
*
|
||||
* Cascading grid layout library
|
||||
* http://masonry.desandro.com
|
||||
* MIT License
|
||||
* by David DeSandro
|
||||
*/
|
||||
!function(a){"use strict";var b=a.Masonry;b.prototype._remapV2Options=function(){this._remapOption("gutterWidth","gutter"),this._remapOption("isResizable","isResizeBound"),this._remapOption("isRTL","isOriginLeft",function(a){return!a});var a=this.options.isAnimated;if(void 0!==a&&(this.options.transitionDuration=a?this.options.transitionDuration:0),void 0===a||a){var b=this.options.animationOptions,c=b&&b.duration;c&&(this.options.transitionDuration="string"==typeof c?c:c+"ms")}},b.prototype._remapOption=function(a,b,c){var d=this.options[a];void 0!==d&&(this.options[b]=c?c(d):d)};var c=b.prototype._create;b.prototype._create=function(){var a=this;this._remapV2Options(),c.apply(this,arguments),setTimeout(function(){jQuery(a.element).addClass("masonry")},0)};var d=b.prototype.layout;b.prototype.layout=function(){this._remapV2Options(),d.apply(this,arguments)};var e=b.prototype.option;b.prototype.option=function(){e.apply(this,arguments),this._remapV2Options()};var f=b.prototype._itemize;b.prototype._itemize=function(a){var b=f.apply(this,arguments);return jQuery(a).addClass("masonry-brick"),b};var g=b.prototype.measureColumns;b.prototype.measureColumns=function(){var a=this.options.columnWidth;a&&"function"==typeof a&&(this.getContainerWidth(),this.columnWidth=a(this.containerWidth)),g.apply(this,arguments)},b.prototype.reload=function(){this.reloadItems.apply(this,arguments),this.layout.apply(this)};var h=b.prototype.destroy;b.prototype.destroy=function(){var a=this.getItemElements();jQuery(this.element).removeClass("masonry"),jQuery(a).removeClass("masonry-brick"),h.apply(this,arguments)}}(window);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* jQuery.query - Query String Modification and Creation for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/8/13
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 2.2.3
|
||||
*
|
||||
**/
|
||||
!function(e){var t=e.separator||"&",l=!1!==e.spaces,n=(e.suffix,!1!==e.prefix?!0===e.hash?"#":"?":""),i=!1!==e.numbers;jQuery.query=new function(){function c(e,t){return null!=e&&null!==e&&(!t||e.constructor==t)}function u(e){for(var t,n=/\[([^[]*)\]/g,r=/^([^[]+)(\[.*\])?$/.exec(e),e=r[1],u=[];t=n.exec(r[2]);)u.push(t[1]);return[e,u]}function o(e,t,n){var r=t.shift();if("object"!=typeof e&&(e=null),""===r)if(c(e=e||[],Array))e.push(0==t.length?n:o(null,t.slice(0),n));else if(c(e,Object)){for(var u=0;null!=e[u++];);e[--u]=0==t.length?n:o(e[u],t.slice(0),n)}else(e=[]).push(0==t.length?n:o(null,t.slice(0),n));else if(r&&r.match(/^\s*[0-9]+\s*$/))(e=e||[])[i=parseInt(r,10)]=0==t.length?n:o(e[i],t.slice(0),n);else{if(!r)return n;var i=r.replace(/^\s*|\s*$/g,"");if(c(e=e||{},Array)){for(var s={},u=0;u<e.length;++u)s[u]=e[u];e=s}e[i]=0==t.length?n:o(e[i],t.slice(0),n)}return e}function r(e){var n=this;return n.keys={},e.queryObject?jQuery.each(e.get(),function(e,t){n.SET(e,t)}):n.parseNew.apply(n,arguments),n}return r.prototype={queryObject:!0,parseNew:function(){var n=this;return n.keys={},jQuery.each(arguments,function(){var e=""+this;e=(e=e.replace(/^[?#]/,"")).replace(/[;&]$/,""),l&&(e=e.replace(/[+]/g," ")),jQuery.each(e.split(/[&;]/),function(){var e=decodeURIComponent(this.split("=")[0]||""),t=decodeURIComponent(this.split("=")[1]||"");e&&(i&&(/^[+-]?[0-9]+\.[0-9]*$/.test(t)?t=parseFloat(t):/^[+-]?[1-9][0-9]*$/.test(t)&&(t=parseInt(t,10))),n.SET(e,t=!t&&0!==t||t))})}),n},has:function(e,t){e=this.get(e);return c(e,t)},GET:function(e){if(!c(e))return this.keys;for(var e=u(e),t=e[0],n=e[1],r=this.keys[t];null!=r&&0!=n.length;)r=r[n.shift()];return"number"==typeof r?r:r||""},get:function(e){e=this.GET(e);return c(e,Object)?jQuery.extend(!0,{},e):c(e,Array)?e.slice(0):e},SET:function(e,t){var n,r;return e.includes("__proto__")||e.includes("constructor")||e.includes("prototype")||(t=c(t)?t:null,n=(e=u(e))[0],e=e[1],r=this.keys[n],this.keys[n]=o(r,e.slice(0),t)),this},set:function(e,t){return this.copy().SET(e,t)},REMOVE:function(e,t){if(t){var n=this.GET(e);if(c(n,Array)){for(tval in n)n[tval]=n[tval].toString();var r=$.inArray(t,n);if(!(0<=r))return;e=(e=n.splice(r,1))[r]}else if(t!=n)return}return this.SET(e,null).COMPACT()},remove:function(e,t){return this.copy().REMOVE(e,t)},EMPTY:function(){var n=this;return jQuery.each(n.keys,function(e,t){delete n.keys[e]}),n},load:function(e){var t=e.replace(/^.*?[#](.+?)(?:\?.+)?$/,"$1"),n=e.replace(/^.*?[?](.+?)(?:#.+)?$/,"$1");return new r(e.length==n.length?"":n,e.length==t.length?"":t)},empty:function(){return this.copy().EMPTY()},copy:function(){return new r(this)},COMPACT:function(){return this.keys=function r(e){var u="object"==typeof e?c(e,Array)?[]:{}:e;return"object"==typeof e&&jQuery.each(e,function(e,t){if(!c(t))return!0;var n;n=u,t=r(t),c(n,Array)?n.push(t):n[e]=t}),u}(this.keys),this},compact:function(){return this.copy().COMPACT()},toString:function(){function u(e,t){function r(e){return(t&&""!=t?[t,"[",e,"]"]:[e]).join("")}jQuery.each(e,function(e,t){var n;"object"==typeof t?u(t,r(e)):(n=i,e=r(e),c(t=t)&&!1!==t&&(e=[s(e)],!0!==t&&(e.push("="),e.push(s(t))),n.push(e.join(""))))})}var e=[],i=[],s=function(e){return e+="",e=encodeURIComponent(e),e=l?e.replace(/%20/g,"+"):e};return u(this.keys),0<i.length&&e.push(n),e.push(i.join(t)),e.join("")}},new r(location.search,location.hash)}}(jQuery.query||{});
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
(function($){$.scheduler=function(){this.bucket={};return;};$.scheduler.prototype={schedule:function(){var ctx={"id":null,"time":1000,"repeat":false,"protect":false,"obj":null,"func":function(){},"args":[]};function _isfn(fn){return(!!fn&&typeof fn!="string"&&typeof fn[0]=="undefined"&&RegExp("function","i").test(fn+""));};var i=0;var override=false;if(typeof arguments[i]=="object"&&arguments.length>1){override=true;i++;}
|
||||
if(typeof arguments[i]=="object"){for(var option in arguments[i])
|
||||
if(typeof ctx[option]!="undefined")
|
||||
ctx[option]=arguments[i][option];i++;}
|
||||
if(typeof arguments[i]=="number"||(typeof arguments[i]=="string"&&arguments[i].match(RegExp("^[0-9]+[smhdw]$"))))
|
||||
ctx["time"]=arguments[i++];if(typeof arguments[i]=="boolean")
|
||||
ctx["repeat"]=arguments[i++];if(typeof arguments[i]=="boolean")
|
||||
ctx["protect"]=arguments[i++];if(typeof arguments[i]=="object"&&typeof arguments[i+1]=="string"&&_isfn(arguments[i][arguments[i+1]])){ctx["obj"]=arguments[i++];ctx["func"]=arguments[i++];}
|
||||
else if(typeof arguments[i]!="undefined"&&(_isfn(arguments[i])||typeof arguments[i]=="string"))
|
||||
ctx["func"]=arguments[i++];while(typeof arguments[i]!="undefined")
|
||||
ctx["args"].push(arguments[i++]);if(override){if(typeof arguments[1]=="object"){for(var option in arguments[0])
|
||||
if(typeof ctx[option]!="undefined"&&typeof arguments[1][option]=="undefined")
|
||||
ctx[option]=arguments[0][option];}
|
||||
else{for(var option in arguments[0])
|
||||
if(typeof ctx[option]!="undefined")
|
||||
ctx[option]=arguments[0][option];}
|
||||
i++;}
|
||||
ctx["_scheduler"]=this;ctx["_handle"]=null;var match=String(ctx["time"]).match(RegExp("^([0-9]+)([smhdw])$"));if(match&&match[0]!="undefined"&&match[1]!="undefined")
|
||||
ctx["time"]=String(parseInt(match[1])*{s:1000,m:1000*60,h:1000*60*60,d:1000*60*60*24,w:1000*60*60*24*7}[match[2]]);if(ctx["id"]==null)
|
||||
ctx["id"]=(String(ctx["repeat"])+":"
|
||||
+String(ctx["protect"])+":"
|
||||
+String(ctx["time"])+":"
|
||||
+String(ctx["obj"])+":"
|
||||
+String(ctx["func"])+":"
|
||||
+String(ctx["args"]));if(ctx["protect"])
|
||||
if(typeof this.bucket[ctx["id"]]!="undefined")
|
||||
return this.bucket[ctx["id"]];if(!_isfn(ctx["func"])){if(ctx["obj"]!=null&&typeof ctx["obj"]=="object"&&typeof ctx["func"]=="string"&&_isfn(ctx["obj"][ctx["func"]]))
|
||||
ctx["func"]=ctx["obj"][ctx["func"]];else
|
||||
ctx["func"]=eval("function () { "+ctx["func"]+" }");}
|
||||
ctx["_handle"]=this._schedule(ctx);this.bucket[ctx["id"]]=ctx;return ctx;},reschedule:function(ctx){if(typeof ctx=="string")
|
||||
ctx=this.bucket[ctx];ctx["_handle"]=this._schedule(ctx);return ctx;},_schedule:function(ctx){var trampoline=function(){var obj=(ctx["obj"]!=null?ctx["obj"]:ctx);(ctx["func"]).apply(obj,ctx["args"]);if(typeof(ctx["_scheduler"]).bucket[ctx["id"]]!="undefined"&&ctx["repeat"])
|
||||
(ctx["_scheduler"])._schedule(ctx);else
|
||||
delete(ctx["_scheduler"]).bucket[ctx["id"]];};return setTimeout(trampoline,ctx["time"]);},cancel:function(ctx){if(typeof ctx=="string")
|
||||
ctx=this.bucket[ctx];if(typeof ctx=="object"){clearTimeout(ctx["_handle"]);delete this.bucket[ctx["id"]];}}};$.extend({scheduler$:new $.scheduler(),schedule:function(){return $.scheduler$.schedule.apply($.scheduler$,arguments)},reschedule:function(){return $.scheduler$.reschedule.apply($.scheduler$,arguments)},cancel:function(){return $.scheduler$.cancel.apply($.scheduler$,arguments)}});$.fn.extend({schedule:function(){var a=[{}];for(var i=0;i<arguments.length;i++)
|
||||
a.push(arguments[i]);return this.each(function(){a[0]={"id":this,"obj":this};return $.schedule.apply($,a);});}});})(jQuery);
|
||||
@@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* jQuery serializeObject - v0.2-wp - 1/20/2010
|
||||
* http://benalman.com/projects/jquery-misc-plugins/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
|
||||
// Whereas .serializeArray() serializes a form into an array, .serializeObject()
|
||||
// serializes a form into an (arguably more useful) object.
|
||||
|
||||
(function($,undefined){
|
||||
'$:nomunge'; // Used by YUI compressor.
|
||||
|
||||
$.fn.serializeObject = function(){
|
||||
var obj = {};
|
||||
|
||||
$.each( this.serializeArray(), function(i,o){
|
||||
var n = o.name,
|
||||
v = o.value;
|
||||
|
||||
obj[n] = obj[n] === undefined ? v
|
||||
: Array.isArray( obj[n] ) ? obj[n].concat( v )
|
||||
: [ obj[n], v ];
|
||||
});
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,99 @@
|
||||
(function($){
|
||||
$.fn.filter_visible = function(depth) {
|
||||
depth = depth || 3;
|
||||
var is_visible = function() {
|
||||
var p = $(this), i;
|
||||
for(i=0; i<depth-1; ++i) {
|
||||
if (!p.is(':visible')) return false;
|
||||
p = p.parent();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return this.filter(is_visible);
|
||||
};
|
||||
$.table_hotkeys = function(table, keys, opts) {
|
||||
opts = $.extend($.table_hotkeys.defaults, opts);
|
||||
var selected_class, destructive_class, set_current_row, adjacent_row_callback, get_adjacent_row, adjacent_row, prev_row, next_row, check, get_first_row, get_last_row, make_key_callback, first_row;
|
||||
|
||||
selected_class = opts.class_prefix + opts.selected_suffix;
|
||||
destructive_class = opts.class_prefix + opts.destructive_suffix;
|
||||
set_current_row = function (tr) {
|
||||
if ($.table_hotkeys.current_row) $.table_hotkeys.current_row.removeClass(selected_class);
|
||||
tr.addClass(selected_class);
|
||||
tr[0].scrollIntoView(false);
|
||||
$.table_hotkeys.current_row = tr;
|
||||
};
|
||||
adjacent_row_callback = function(which) {
|
||||
if (!adjacent_row(which) && typeof opts[which+'_page_link_cb'] === 'function' ) {
|
||||
opts[which+'_page_link_cb']();
|
||||
}
|
||||
};
|
||||
get_adjacent_row = function(which) {
|
||||
var first_row, method;
|
||||
|
||||
if (!$.table_hotkeys.current_row) {
|
||||
first_row = get_first_row();
|
||||
$.table_hotkeys.current_row = first_row;
|
||||
return first_row[0];
|
||||
}
|
||||
method = 'prev' == which? $.fn.prevAll : $.fn.nextAll;
|
||||
return method.call($.table_hotkeys.current_row, opts.cycle_expr).filter_visible()[0];
|
||||
};
|
||||
adjacent_row = function(which) {
|
||||
var adj = get_adjacent_row(which);
|
||||
if (!adj) return false;
|
||||
set_current_row($(adj));
|
||||
return true;
|
||||
};
|
||||
prev_row = function() { return adjacent_row('prev'); };
|
||||
next_row = function() { return adjacent_row('next'); };
|
||||
check = function() {
|
||||
$(opts.checkbox_expr, $.table_hotkeys.current_row).each(function() {
|
||||
this.checked = !this.checked;
|
||||
});
|
||||
};
|
||||
get_first_row = function() {
|
||||
return $(opts.cycle_expr, table).filter_visible().eq(opts.start_row_index);
|
||||
};
|
||||
get_last_row = function() {
|
||||
var rows = $(opts.cycle_expr, table).filter_visible();
|
||||
return rows.eq(rows.length-1);
|
||||
};
|
||||
make_key_callback = function(expr) {
|
||||
return function() {
|
||||
if ( null == $.table_hotkeys.current_row ) return false;
|
||||
var clickable = $(expr, $.table_hotkeys.current_row);
|
||||
if (!clickable.length) return false;
|
||||
if (clickable.is('.'+destructive_class)) next_row() || prev_row();
|
||||
clickable.trigger( 'click' );
|
||||
};
|
||||
};
|
||||
first_row = get_first_row();
|
||||
if (!first_row.length) return;
|
||||
if (opts.highlight_first)
|
||||
set_current_row(first_row);
|
||||
else if (opts.highlight_last)
|
||||
set_current_row(get_last_row());
|
||||
$.hotkeys.add(opts.prev_key, opts.hotkeys_opts, function() {return adjacent_row_callback('prev');});
|
||||
$.hotkeys.add(opts.next_key, opts.hotkeys_opts, function() {return adjacent_row_callback('next');});
|
||||
$.hotkeys.add(opts.mark_key, opts.hotkeys_opts, check);
|
||||
$.each(keys, function() {
|
||||
var callback, key;
|
||||
|
||||
if ( typeof this[1] === 'function' ) {
|
||||
callback = this[1];
|
||||
key = this[0];
|
||||
$.hotkeys.add(key, opts.hotkeys_opts, function(event) { return callback(event, $.table_hotkeys.current_row); });
|
||||
} else {
|
||||
key = this;
|
||||
$.hotkeys.add(key, opts.hotkeys_opts, make_key_callback('.'+opts.class_prefix+key));
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
$.table_hotkeys.current_row = null;
|
||||
$.table_hotkeys.defaults = {cycle_expr: 'tr', class_prefix: 'vim-', selected_suffix: 'current',
|
||||
destructive_suffix: 'destructive', hotkeys_opts: {disableInInput: true, type: 'keypress'},
|
||||
checkbox_expr: ':checkbox', next_key: 'j', prev_key: 'k', mark_key: 'x',
|
||||
start_row_index: 2, highlight_first: false, highlight_last: false, next_page_link_cb: false, prev_page_link_cb: false};
|
||||
})(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
(function(a){a.fn.filter_visible=function(c){c=c||3;var b=function(){var e=a(this),d;for(d=0;d<c-1;++d){if(!e.is(":visible")){return false}e=e.parent()}return true};return this.filter(b)};a.table_hotkeys=function(p,q,b){b=a.extend(a.table_hotkeys.defaults,b);var i,l,e,f,m,d,k,o,c,h,g,n,j;i=b.class_prefix+b.selected_suffix;l=b.class_prefix+b.destructive_suffix;e=function(r){if(a.table_hotkeys.current_row){a.table_hotkeys.current_row.removeClass(i)}r.addClass(i);r[0].scrollIntoView(false);a.table_hotkeys.current_row=r};f=function(r){if(!d(r)&&a.isFunction(b[r+"_page_link_cb"])){b[r+"_page_link_cb"]()}};m=function(s){var r,t;if(!a.table_hotkeys.current_row){r=h();a.table_hotkeys.current_row=r;return r[0]}t="prev"==s?a.fn.prevAll:a.fn.nextAll;return t.call(a.table_hotkeys.current_row,b.cycle_expr).filter_visible()[0]};d=function(s){var r=m(s);if(!r){return false}e(a(r));return true};k=function(){return d("prev")};o=function(){return d("next")};c=function(){a(b.checkbox_expr,a.table_hotkeys.current_row).each(function(){this.checked=!this.checked})};h=function(){return a(b.cycle_expr,p).filter_visible().eq(b.start_row_index)};g=function(){var r=a(b.cycle_expr,p).filter_visible();return r.eq(r.length-1)};n=function(r){return function(){if(null==a.table_hotkeys.current_row){return false}var s=a(r,a.table_hotkeys.current_row);if(!s.length){return false}if(s.is("."+l)){o()||k()}s.click()}};j=h();if(!j.length){return}if(b.highlight_first){e(j)}else{if(b.highlight_last){e(g())}}a.hotkeys.add(b.prev_key,b.hotkeys_opts,function(){return f("prev")});a.hotkeys.add(b.next_key,b.hotkeys_opts,function(){return f("next")});a.hotkeys.add(b.mark_key,b.hotkeys_opts,c);a.each(q,function(){var s,r;if(a.isFunction(this[1])){s=this[1];r=this[0];a.hotkeys.add(r,b.hotkeys_opts,function(t){return s(t,a.table_hotkeys.current_row)})}else{r=this;a.hotkeys.add(r,b.hotkeys_opts,n("."+b.class_prefix+r))}})};a.table_hotkeys.current_row=null;a.table_hotkeys.defaults={cycle_expr:"tr",class_prefix:"vim-",selected_suffix:"current",destructive_suffix:"destructive",hotkeys_opts:{disableInInput:true,type:"keypress"},checkbox_expr:":checkbox",next_key:"j",prev_key:"k",mark_key:"x",start_row_index:2,highlight_first:false,highlight_last:false,next_page_link_cb:false,prev_page_link_cb:false}})(jQuery);
|
||||
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* jQuery UI Touch Punch 0.2.2
|
||||
*
|
||||
* Copyright 2011, Dave Furfero
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.widget.js
|
||||
* jquery.ui.mouse.js
|
||||
*/
|
||||
(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f)}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown")};c._touchMove=function(f){if(!a){return}this._touchMoved=true;d(f,"mousemove")};c._touchEnd=function(f){if(!a){return}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click")}a=false};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f)}})(jQuery);
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* jquery.suggest 1.1b - 2007-08-06
|
||||
* Patched by Mark Jaquith with Alexander Dick's "multiple items" patch to allow for auto-suggesting of more than one tag before submitting
|
||||
* See: http://www.vulgarisoip.com/2007/06/29/jquerysuggest-an-alternative-jquery-based-autocomplete-library/#comment-7228
|
||||
*
|
||||
* Uses code and techniques from following libraries:
|
||||
* 1. http://www.dyve.net/jquery/?autocomplete
|
||||
* 2. http://dev.jquery.com/browser/trunk/plugins/interface/iautocompleter.js
|
||||
*
|
||||
* All the new stuff written by Peter Vulgaris (www.vulgarisoip.com)
|
||||
* Feel free to do whatever you want with this file
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
$.suggest = function(input, options) {
|
||||
var $input, $results, timeout, prevLength, cache, cacheSize;
|
||||
|
||||
$input = $(input).attr("autocomplete", "off");
|
||||
$results = $("<ul/>");
|
||||
|
||||
timeout = false; // hold timeout ID for suggestion results to appear
|
||||
prevLength = 0; // last recorded length of $input.val()
|
||||
cache = []; // cache MRU list
|
||||
cacheSize = 0; // size of cache in chars (bytes?)
|
||||
|
||||
$results.addClass(options.resultsClass).appendTo('body');
|
||||
|
||||
|
||||
resetPosition();
|
||||
$(window)
|
||||
.on( 'load', resetPosition ) // just in case user is changing size of page while loading
|
||||
.on( 'resize', resetPosition );
|
||||
|
||||
$input.blur(function() {
|
||||
setTimeout(function() { $results.hide() }, 200);
|
||||
});
|
||||
|
||||
$input.keydown(processKey);
|
||||
|
||||
function resetPosition() {
|
||||
// requires jquery.dimension plugin
|
||||
var offset = $input.offset();
|
||||
$results.css({
|
||||
top: (offset.top + input.offsetHeight) + 'px',
|
||||
left: offset.left + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function processKey(e) {
|
||||
|
||||
// handling up/down/escape requires results to be visible
|
||||
// handling enter/tab requires that AND a result to be selected
|
||||
if ((/27$|38$|40$/.test(e.keyCode) && $results.is(':visible')) ||
|
||||
(/^13$|^9$/.test(e.keyCode) && getCurrentResult())) {
|
||||
|
||||
if (e.preventDefault)
|
||||
e.preventDefault();
|
||||
if (e.stopPropagation)
|
||||
e.stopPropagation();
|
||||
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
|
||||
switch(e.keyCode) {
|
||||
|
||||
case 38: // up
|
||||
prevResult();
|
||||
break;
|
||||
|
||||
case 40: // down
|
||||
nextResult();
|
||||
break;
|
||||
|
||||
case 9: // tab
|
||||
case 13: // return
|
||||
selectCurrentResult();
|
||||
break;
|
||||
|
||||
case 27: // escape
|
||||
$results.hide();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else if ($input.val().length != prevLength) {
|
||||
|
||||
if (timeout)
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(suggest, options.delay);
|
||||
prevLength = $input.val().length;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function suggest() {
|
||||
|
||||
var q = $.trim($input.val()), multipleSepPos, items;
|
||||
|
||||
if ( options.multiple ) {
|
||||
multipleSepPos = q.lastIndexOf(options.multipleSep);
|
||||
if ( multipleSepPos != -1 ) {
|
||||
q = $.trim(q.substr(multipleSepPos + options.multipleSep.length));
|
||||
}
|
||||
}
|
||||
if (q.length >= options.minchars) {
|
||||
|
||||
cached = checkCache(q);
|
||||
|
||||
if (cached) {
|
||||
|
||||
displayItems(cached['items']);
|
||||
|
||||
} else {
|
||||
|
||||
$.get(options.source, {q: q}, function(txt) {
|
||||
|
||||
$results.hide();
|
||||
|
||||
items = parseTxt(txt, q);
|
||||
|
||||
displayItems(items);
|
||||
addToCache(q, items, txt.length);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$results.hide();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function checkCache(q) {
|
||||
var i;
|
||||
for (i = 0; i < cache.length; i++)
|
||||
if (cache[i]['q'] == q) {
|
||||
cache.unshift(cache.splice(i, 1)[0]);
|
||||
return cache[0];
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function addToCache(q, items, size) {
|
||||
var cached;
|
||||
while (cache.length && (cacheSize + size > options.maxCacheSize)) {
|
||||
cached = cache.pop();
|
||||
cacheSize -= cached['size'];
|
||||
}
|
||||
|
||||
cache.push({
|
||||
q: q,
|
||||
size: size,
|
||||
items: items
|
||||
});
|
||||
|
||||
cacheSize += size;
|
||||
|
||||
}
|
||||
|
||||
function displayItems(items) {
|
||||
var html = '', i;
|
||||
if (!items)
|
||||
return;
|
||||
|
||||
if (!items.length) {
|
||||
$results.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
resetPosition(); // when the form moves after the page has loaded
|
||||
|
||||
for (i = 0; i < items.length; i++)
|
||||
html += '<li>' + items[i] + '</li>';
|
||||
|
||||
$results.html(html).show();
|
||||
|
||||
$results
|
||||
.children('li')
|
||||
.mouseover(function() {
|
||||
$results.children('li').removeClass(options.selectClass);
|
||||
$(this).addClass(options.selectClass);
|
||||
})
|
||||
.click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
selectCurrentResult();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function parseTxt(txt, q) {
|
||||
|
||||
var items = [], tokens = txt.split(options.delimiter), i, token;
|
||||
|
||||
// parse returned data for non-empty items
|
||||
for (i = 0; i < tokens.length; i++) {
|
||||
token = $.trim(tokens[i]);
|
||||
if (token) {
|
||||
token = token.replace(
|
||||
new RegExp(q, 'ig'),
|
||||
function(q) { return '<span class="' + options.matchClass + '">' + q + '</span>' }
|
||||
);
|
||||
items[items.length] = token;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function getCurrentResult() {
|
||||
var $currentResult;
|
||||
if (!$results.is(':visible'))
|
||||
return false;
|
||||
|
||||
$currentResult = $results.children('li.' + options.selectClass);
|
||||
|
||||
if (!$currentResult.length)
|
||||
$currentResult = false;
|
||||
|
||||
return $currentResult;
|
||||
|
||||
}
|
||||
|
||||
function selectCurrentResult() {
|
||||
|
||||
$currentResult = getCurrentResult();
|
||||
|
||||
if ($currentResult) {
|
||||
if ( options.multiple ) {
|
||||
if ( $input.val().indexOf(options.multipleSep) != -1 ) {
|
||||
$currentVal = $input.val().substr( 0, ( $input.val().lastIndexOf(options.multipleSep) + options.multipleSep.length ) ) + ' ';
|
||||
} else {
|
||||
$currentVal = "";
|
||||
}
|
||||
$input.val( $currentVal + $currentResult.text() + options.multipleSep + ' ' );
|
||||
$input.focus();
|
||||
} else {
|
||||
$input.val($currentResult.text());
|
||||
}
|
||||
$results.hide();
|
||||
$input.trigger('change');
|
||||
|
||||
if (options.onSelect)
|
||||
options.onSelect.apply($input[0]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function nextResult() {
|
||||
|
||||
$currentResult = getCurrentResult();
|
||||
|
||||
if ($currentResult)
|
||||
$currentResult
|
||||
.removeClass(options.selectClass)
|
||||
.next()
|
||||
.addClass(options.selectClass);
|
||||
else
|
||||
$results.children('li:first-child').addClass(options.selectClass);
|
||||
|
||||
}
|
||||
|
||||
function prevResult() {
|
||||
var $currentResult = getCurrentResult();
|
||||
|
||||
if ($currentResult)
|
||||
$currentResult
|
||||
.removeClass(options.selectClass)
|
||||
.prev()
|
||||
.addClass(options.selectClass);
|
||||
else
|
||||
$results.children('li:last-child').addClass(options.selectClass);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.suggest = function(source, options) {
|
||||
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
options = options || {};
|
||||
options.multiple = options.multiple || false;
|
||||
options.multipleSep = options.multipleSep || ",";
|
||||
options.source = source;
|
||||
options.delay = options.delay || 100;
|
||||
options.resultsClass = options.resultsClass || 'ac_results';
|
||||
options.selectClass = options.selectClass || 'ac_over';
|
||||
options.matchClass = options.matchClass || 'ac_match';
|
||||
options.minchars = options.minchars || 2;
|
||||
options.delimiter = options.delimiter || '\n';
|
||||
options.onSelect = options.onSelect || false;
|
||||
options.maxCacheSize = options.maxCacheSize || 65536;
|
||||
|
||||
this.each(function() {
|
||||
new $.suggest(this, options);
|
||||
});
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){a.suggest=function(b,c){function d(){var a=o.offset();p.css({top:a.top+b.offsetHeight+"px",left:a.left+"px"})}function e(a){if(/27$|38$|40$/.test(a.keyCode)&&p.is(":visible")||/^13$|^9$/.test(a.keyCode)&&k())switch(a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0,a.returnValue=!1,a.keyCode){case 38:n();break;case 40:m();break;case 9:case 13:l();break;case 27:p.hide()}else o.val().length!=r&&(q&&clearTimeout(q),q=setTimeout(f,c.delay),r=o.val().length)}function f(){var b,d,e=a.trim(o.val());c.multiple&&(b=e.lastIndexOf(c.multipleSep),-1!=b&&(e=a.trim(e.substr(b+c.multipleSep.length)))),e.length>=c.minchars?(cached=g(e),cached?i(cached.items):a.get(c.source,{q:e},function(a){p.hide(),d=j(a,e),i(d),h(e,d,a.length)})):p.hide()}function g(a){var b;for(b=0;b<s.length;b++)if(s[b].q==a)return s.unshift(s.splice(b,1)[0]),s[0];return!1}function h(a,b,d){for(var e;s.length&&t+d>c.maxCacheSize;)e=s.pop(),t-=e.size;s.push({q:a,size:d,items:b}),t+=d}function i(b){var e,f="";if(b){if(!b.length)return void p.hide();for(d(),e=0;e<b.length;e++)f+="<li>"+b[e]+"</li>";p.html(f).show(),p.children("li").mouseover(function(){p.children("li").removeClass(c.selectClass),a(this).addClass(c.selectClass)}).click(function(a){a.preventDefault(),a.stopPropagation(),l()})}}function j(b,d){var e,f,g=[],h=b.split(c.delimiter);for(e=0;e<h.length;e++)f=a.trim(h[e]),f&&(f=f.replace(new RegExp(d,"ig"),function(a){return'<span class="'+c.matchClass+'">'+a+"</span>"}),g[g.length]=f);return g}function k(){var a;return p.is(":visible")?(a=p.children("li."+c.selectClass),a.length||(a=!1),a):!1}function l(){$currentResult=k(),$currentResult&&(c.multiple?(-1!=o.val().indexOf(c.multipleSep)?$currentVal=o.val().substr(0,o.val().lastIndexOf(c.multipleSep)+c.multipleSep.length)+" ":$currentVal="",o.val($currentVal+$currentResult.text()+c.multipleSep+" "),o.focus()):o.val($currentResult.text()),p.hide(),o.trigger("change"),c.onSelect&&c.onSelect.apply(o[0]))}function m(){$currentResult=k(),$currentResult?$currentResult.removeClass(c.selectClass).next().addClass(c.selectClass):p.children("li:first-child").addClass(c.selectClass)}function n(){var a=k();a?a.removeClass(c.selectClass).prev().addClass(c.selectClass):p.children("li:last-child").addClass(c.selectClass)}var o,p,q,r,s,t;o=a(b).attr("autocomplete","off"),p=a("<ul/>"),q=!1,r=0,s=[],t=0,p.addClass(c.resultsClass).appendTo("body"),d(),a(window).on("load",d).on("resize",d),o.blur(function(){setTimeout(function(){p.hide()},200)}),o.keydown(e)},a.fn.suggest=function(b,c){return b?(c=c||{},c.multiple=c.multiple||!1,c.multipleSep=c.multipleSep||",",c.source=b,c.delay=c.delay||100,c.resultsClass=c.resultsClass||"ac_results",c.selectClass=c.selectClass||"ac_over",c.matchClass=c.matchClass||"ac_match",c.minchars=c.minchars||2,c.delimiter=c.delimiter||"\n",c.onSelect=c.onSelect||!1,c.maxCacheSize=c.maxCacheSize||65536,this.each(function(){new a.suggest(this,c)}),this):void 0}}(jQuery);
|
||||
+619
@@ -0,0 +1,619 @@
|
||||
/*!
|
||||
* jQuery UI Accordion 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Accordion
|
||||
//>>group: Widgets
|
||||
/* eslint-disable max-len */
|
||||
//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
|
||||
/* eslint-enable max-len */
|
||||
//>>docs: http://api.jqueryui.com/accordion/
|
||||
//>>demos: http://jqueryui.com/accordion/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/accordion.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
return $.widget( "ui.accordion", {
|
||||
version: "1.13.2",
|
||||
options: {
|
||||
active: 0,
|
||||
animate: {},
|
||||
classes: {
|
||||
"ui-accordion-header": "ui-corner-top",
|
||||
"ui-accordion-header-collapsed": "ui-corner-all",
|
||||
"ui-accordion-content": "ui-corner-bottom"
|
||||
},
|
||||
collapsible: false,
|
||||
event: "click",
|
||||
header: function( elem ) {
|
||||
return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
|
||||
},
|
||||
heightStyle: "auto",
|
||||
icons: {
|
||||
activeHeader: "ui-icon-triangle-1-s",
|
||||
header: "ui-icon-triangle-1-e"
|
||||
},
|
||||
|
||||
// Callbacks
|
||||
activate: null,
|
||||
beforeActivate: null
|
||||
},
|
||||
|
||||
hideProps: {
|
||||
borderTopWidth: "hide",
|
||||
borderBottomWidth: "hide",
|
||||
paddingTop: "hide",
|
||||
paddingBottom: "hide",
|
||||
height: "hide"
|
||||
},
|
||||
|
||||
showProps: {
|
||||
borderTopWidth: "show",
|
||||
borderBottomWidth: "show",
|
||||
paddingTop: "show",
|
||||
paddingBottom: "show",
|
||||
height: "show"
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
var options = this.options;
|
||||
|
||||
this.prevShow = this.prevHide = $();
|
||||
this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
|
||||
this.element.attr( "role", "tablist" );
|
||||
|
||||
// Don't allow collapsible: false and active: false / null
|
||||
if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
|
||||
options.active = 0;
|
||||
}
|
||||
|
||||
this._processPanels();
|
||||
|
||||
// handle negative values
|
||||
if ( options.active < 0 ) {
|
||||
options.active += this.headers.length;
|
||||
}
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
_getCreateEventData: function() {
|
||||
return {
|
||||
header: this.active,
|
||||
panel: !this.active.length ? $() : this.active.next()
|
||||
};
|
||||
},
|
||||
|
||||
_createIcons: function() {
|
||||
var icon, children,
|
||||
icons = this.options.icons;
|
||||
|
||||
if ( icons ) {
|
||||
icon = $( "<span>" );
|
||||
this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
|
||||
icon.prependTo( this.headers );
|
||||
children = this.active.children( ".ui-accordion-header-icon" );
|
||||
this._removeClass( children, icons.header )
|
||||
._addClass( children, null, icons.activeHeader )
|
||||
._addClass( this.headers, "ui-accordion-icons" );
|
||||
}
|
||||
},
|
||||
|
||||
_destroyIcons: function() {
|
||||
this._removeClass( this.headers, "ui-accordion-icons" );
|
||||
this.headers.children( ".ui-accordion-header-icon" ).remove();
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
var contents;
|
||||
|
||||
// Clean up main element
|
||||
this.element.removeAttr( "role" );
|
||||
|
||||
// Clean up headers
|
||||
this.headers
|
||||
.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
|
||||
.removeUniqueId();
|
||||
|
||||
this._destroyIcons();
|
||||
|
||||
// Clean up content panels
|
||||
contents = this.headers.next()
|
||||
.css( "display", "" )
|
||||
.removeAttr( "role aria-hidden aria-labelledby" )
|
||||
.removeUniqueId();
|
||||
|
||||
if ( this.options.heightStyle !== "content" ) {
|
||||
contents.css( "height", "" );
|
||||
}
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
if ( key === "active" ) {
|
||||
|
||||
// _activate() will handle invalid values and update this.options
|
||||
this._activate( value );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( key === "event" ) {
|
||||
if ( this.options.event ) {
|
||||
this._off( this.headers, this.options.event );
|
||||
}
|
||||
this._setupEvents( value );
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
|
||||
// Setting collapsible: false while collapsed; open first panel
|
||||
if ( key === "collapsible" && !value && this.options.active === false ) {
|
||||
this._activate( 0 );
|
||||
}
|
||||
|
||||
if ( key === "icons" ) {
|
||||
this._destroyIcons();
|
||||
if ( value ) {
|
||||
this._createIcons();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_setOptionDisabled: function( value ) {
|
||||
this._super( value );
|
||||
|
||||
this.element.attr( "aria-disabled", value );
|
||||
|
||||
// Support: IE8 Only
|
||||
// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
|
||||
// so we need to add the disabled class to the headers and panels
|
||||
this._toggleClass( null, "ui-state-disabled", !!value );
|
||||
this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
|
||||
!!value );
|
||||
},
|
||||
|
||||
_keydown: function( event ) {
|
||||
if ( event.altKey || event.ctrlKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keyCode = $.ui.keyCode,
|
||||
length = this.headers.length,
|
||||
currentIndex = this.headers.index( event.target ),
|
||||
toFocus = false;
|
||||
|
||||
switch ( event.keyCode ) {
|
||||
case keyCode.RIGHT:
|
||||
case keyCode.DOWN:
|
||||
toFocus = this.headers[ ( currentIndex + 1 ) % length ];
|
||||
break;
|
||||
case keyCode.LEFT:
|
||||
case keyCode.UP:
|
||||
toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
|
||||
break;
|
||||
case keyCode.SPACE:
|
||||
case keyCode.ENTER:
|
||||
this._eventHandler( event );
|
||||
break;
|
||||
case keyCode.HOME:
|
||||
toFocus = this.headers[ 0 ];
|
||||
break;
|
||||
case keyCode.END:
|
||||
toFocus = this.headers[ length - 1 ];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( toFocus ) {
|
||||
$( event.target ).attr( "tabIndex", -1 );
|
||||
$( toFocus ).attr( "tabIndex", 0 );
|
||||
$( toFocus ).trigger( "focus" );
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
_panelKeyDown: function( event ) {
|
||||
if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
|
||||
$( event.currentTarget ).prev().trigger( "focus" );
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
var options = this.options;
|
||||
this._processPanels();
|
||||
|
||||
// Was collapsed or no panel
|
||||
if ( ( options.active === false && options.collapsible === true ) ||
|
||||
!this.headers.length ) {
|
||||
options.active = false;
|
||||
this.active = $();
|
||||
|
||||
// active false only when collapsible is true
|
||||
} else if ( options.active === false ) {
|
||||
this._activate( 0 );
|
||||
|
||||
// was active, but active panel is gone
|
||||
} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
|
||||
|
||||
// all remaining panel are disabled
|
||||
if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
|
||||
options.active = false;
|
||||
this.active = $();
|
||||
|
||||
// activate previous panel
|
||||
} else {
|
||||
this._activate( Math.max( 0, options.active - 1 ) );
|
||||
}
|
||||
|
||||
// was active, active panel still exists
|
||||
} else {
|
||||
|
||||
// make sure active index is correct
|
||||
options.active = this.headers.index( this.active );
|
||||
}
|
||||
|
||||
this._destroyIcons();
|
||||
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
_processPanels: function() {
|
||||
var prevHeaders = this.headers,
|
||||
prevPanels = this.panels;
|
||||
|
||||
if ( typeof this.options.header === "function" ) {
|
||||
this.headers = this.options.header( this.element );
|
||||
} else {
|
||||
this.headers = this.element.find( this.options.header );
|
||||
}
|
||||
this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
|
||||
"ui-state-default" );
|
||||
|
||||
this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
|
||||
this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
|
||||
|
||||
// Avoid memory leaks (#10056)
|
||||
if ( prevPanels ) {
|
||||
this._off( prevHeaders.not( this.headers ) );
|
||||
this._off( prevPanels.not( this.panels ) );
|
||||
}
|
||||
},
|
||||
|
||||
_refresh: function() {
|
||||
var maxHeight,
|
||||
options = this.options,
|
||||
heightStyle = options.heightStyle,
|
||||
parent = this.element.parent();
|
||||
|
||||
this.active = this._findActive( options.active );
|
||||
this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
|
||||
._removeClass( this.active, "ui-accordion-header-collapsed" );
|
||||
this._addClass( this.active.next(), "ui-accordion-content-active" );
|
||||
this.active.next().show();
|
||||
|
||||
this.headers
|
||||
.attr( "role", "tab" )
|
||||
.each( function() {
|
||||
var header = $( this ),
|
||||
headerId = header.uniqueId().attr( "id" ),
|
||||
panel = header.next(),
|
||||
panelId = panel.uniqueId().attr( "id" );
|
||||
header.attr( "aria-controls", panelId );
|
||||
panel.attr( "aria-labelledby", headerId );
|
||||
} )
|
||||
.next()
|
||||
.attr( "role", "tabpanel" );
|
||||
|
||||
this.headers
|
||||
.not( this.active )
|
||||
.attr( {
|
||||
"aria-selected": "false",
|
||||
"aria-expanded": "false",
|
||||
tabIndex: -1
|
||||
} )
|
||||
.next()
|
||||
.attr( {
|
||||
"aria-hidden": "true"
|
||||
} )
|
||||
.hide();
|
||||
|
||||
// Make sure at least one header is in the tab order
|
||||
if ( !this.active.length ) {
|
||||
this.headers.eq( 0 ).attr( "tabIndex", 0 );
|
||||
} else {
|
||||
this.active.attr( {
|
||||
"aria-selected": "true",
|
||||
"aria-expanded": "true",
|
||||
tabIndex: 0
|
||||
} )
|
||||
.next()
|
||||
.attr( {
|
||||
"aria-hidden": "false"
|
||||
} );
|
||||
}
|
||||
|
||||
this._createIcons();
|
||||
|
||||
this._setupEvents( options.event );
|
||||
|
||||
if ( heightStyle === "fill" ) {
|
||||
maxHeight = parent.height();
|
||||
this.element.siblings( ":visible" ).each( function() {
|
||||
var elem = $( this ),
|
||||
position = elem.css( "position" );
|
||||
|
||||
if ( position === "absolute" || position === "fixed" ) {
|
||||
return;
|
||||
}
|
||||
maxHeight -= elem.outerHeight( true );
|
||||
} );
|
||||
|
||||
this.headers.each( function() {
|
||||
maxHeight -= $( this ).outerHeight( true );
|
||||
} );
|
||||
|
||||
this.headers.next()
|
||||
.each( function() {
|
||||
$( this ).height( Math.max( 0, maxHeight -
|
||||
$( this ).innerHeight() + $( this ).height() ) );
|
||||
} )
|
||||
.css( "overflow", "auto" );
|
||||
} else if ( heightStyle === "auto" ) {
|
||||
maxHeight = 0;
|
||||
this.headers.next()
|
||||
.each( function() {
|
||||
var isVisible = $( this ).is( ":visible" );
|
||||
if ( !isVisible ) {
|
||||
$( this ).show();
|
||||
}
|
||||
maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
|
||||
if ( !isVisible ) {
|
||||
$( this ).hide();
|
||||
}
|
||||
} )
|
||||
.height( maxHeight );
|
||||
}
|
||||
},
|
||||
|
||||
_activate: function( index ) {
|
||||
var active = this._findActive( index )[ 0 ];
|
||||
|
||||
// Trying to activate the already active panel
|
||||
if ( active === this.active[ 0 ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trying to collapse, simulate a click on the currently active header
|
||||
active = active || this.active[ 0 ];
|
||||
|
||||
this._eventHandler( {
|
||||
target: active,
|
||||
currentTarget: active,
|
||||
preventDefault: $.noop
|
||||
} );
|
||||
},
|
||||
|
||||
_findActive: function( selector ) {
|
||||
return typeof selector === "number" ? this.headers.eq( selector ) : $();
|
||||
},
|
||||
|
||||
_setupEvents: function( event ) {
|
||||
var events = {
|
||||
keydown: "_keydown"
|
||||
};
|
||||
if ( event ) {
|
||||
$.each( event.split( " " ), function( index, eventName ) {
|
||||
events[ eventName ] = "_eventHandler";
|
||||
} );
|
||||
}
|
||||
|
||||
this._off( this.headers.add( this.headers.next() ) );
|
||||
this._on( this.headers, events );
|
||||
this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
|
||||
this._hoverable( this.headers );
|
||||
this._focusable( this.headers );
|
||||
},
|
||||
|
||||
_eventHandler: function( event ) {
|
||||
var activeChildren, clickedChildren,
|
||||
options = this.options,
|
||||
active = this.active,
|
||||
clicked = $( event.currentTarget ),
|
||||
clickedIsActive = clicked[ 0 ] === active[ 0 ],
|
||||
collapsing = clickedIsActive && options.collapsible,
|
||||
toShow = collapsing ? $() : clicked.next(),
|
||||
toHide = active.next(),
|
||||
eventData = {
|
||||
oldHeader: active,
|
||||
oldPanel: toHide,
|
||||
newHeader: collapsing ? $() : clicked,
|
||||
newPanel: toShow
|
||||
};
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (
|
||||
|
||||
// click on active header, but not collapsible
|
||||
( clickedIsActive && !options.collapsible ) ||
|
||||
|
||||
// allow canceling activation
|
||||
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
options.active = collapsing ? false : this.headers.index( clicked );
|
||||
|
||||
// When the call to ._toggle() comes after the class changes
|
||||
// it causes a very odd bug in IE 8 (see #6720)
|
||||
this.active = clickedIsActive ? $() : clicked;
|
||||
this._toggle( eventData );
|
||||
|
||||
// Switch classes
|
||||
// corner classes on the previously active header stay after the animation
|
||||
this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
|
||||
if ( options.icons ) {
|
||||
activeChildren = active.children( ".ui-accordion-header-icon" );
|
||||
this._removeClass( activeChildren, null, options.icons.activeHeader )
|
||||
._addClass( activeChildren, null, options.icons.header );
|
||||
}
|
||||
|
||||
if ( !clickedIsActive ) {
|
||||
this._removeClass( clicked, "ui-accordion-header-collapsed" )
|
||||
._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
|
||||
if ( options.icons ) {
|
||||
clickedChildren = clicked.children( ".ui-accordion-header-icon" );
|
||||
this._removeClass( clickedChildren, null, options.icons.header )
|
||||
._addClass( clickedChildren, null, options.icons.activeHeader );
|
||||
}
|
||||
|
||||
this._addClass( clicked.next(), "ui-accordion-content-active" );
|
||||
}
|
||||
},
|
||||
|
||||
_toggle: function( data ) {
|
||||
var toShow = data.newPanel,
|
||||
toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
|
||||
|
||||
// Handle activating a panel during the animation for another activation
|
||||
this.prevShow.add( this.prevHide ).stop( true, true );
|
||||
this.prevShow = toShow;
|
||||
this.prevHide = toHide;
|
||||
|
||||
if ( this.options.animate ) {
|
||||
this._animate( toShow, toHide, data );
|
||||
} else {
|
||||
toHide.hide();
|
||||
toShow.show();
|
||||
this._toggleComplete( data );
|
||||
}
|
||||
|
||||
toHide.attr( {
|
||||
"aria-hidden": "true"
|
||||
} );
|
||||
toHide.prev().attr( {
|
||||
"aria-selected": "false",
|
||||
"aria-expanded": "false"
|
||||
} );
|
||||
|
||||
// if we're switching panels, remove the old header from the tab order
|
||||
// if we're opening from collapsed state, remove the previous header from the tab order
|
||||
// if we're collapsing, then keep the collapsing header in the tab order
|
||||
if ( toShow.length && toHide.length ) {
|
||||
toHide.prev().attr( {
|
||||
"tabIndex": -1,
|
||||
"aria-expanded": "false"
|
||||
} );
|
||||
} else if ( toShow.length ) {
|
||||
this.headers.filter( function() {
|
||||
return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
|
||||
} )
|
||||
.attr( "tabIndex", -1 );
|
||||
}
|
||||
|
||||
toShow
|
||||
.attr( "aria-hidden", "false" )
|
||||
.prev()
|
||||
.attr( {
|
||||
"aria-selected": "true",
|
||||
"aria-expanded": "true",
|
||||
tabIndex: 0
|
||||
} );
|
||||
},
|
||||
|
||||
_animate: function( toShow, toHide, data ) {
|
||||
var total, easing, duration,
|
||||
that = this,
|
||||
adjust = 0,
|
||||
boxSizing = toShow.css( "box-sizing" ),
|
||||
down = toShow.length &&
|
||||
( !toHide.length || ( toShow.index() < toHide.index() ) ),
|
||||
animate = this.options.animate || {},
|
||||
options = down && animate.down || animate,
|
||||
complete = function() {
|
||||
that._toggleComplete( data );
|
||||
};
|
||||
|
||||
if ( typeof options === "number" ) {
|
||||
duration = options;
|
||||
}
|
||||
if ( typeof options === "string" ) {
|
||||
easing = options;
|
||||
}
|
||||
|
||||
// fall back from options to animation in case of partial down settings
|
||||
easing = easing || options.easing || animate.easing;
|
||||
duration = duration || options.duration || animate.duration;
|
||||
|
||||
if ( !toHide.length ) {
|
||||
return toShow.animate( this.showProps, duration, easing, complete );
|
||||
}
|
||||
if ( !toShow.length ) {
|
||||
return toHide.animate( this.hideProps, duration, easing, complete );
|
||||
}
|
||||
|
||||
total = toShow.show().outerHeight();
|
||||
toHide.animate( this.hideProps, {
|
||||
duration: duration,
|
||||
easing: easing,
|
||||
step: function( now, fx ) {
|
||||
fx.now = Math.round( now );
|
||||
}
|
||||
} );
|
||||
toShow
|
||||
.hide()
|
||||
.animate( this.showProps, {
|
||||
duration: duration,
|
||||
easing: easing,
|
||||
complete: complete,
|
||||
step: function( now, fx ) {
|
||||
fx.now = Math.round( now );
|
||||
if ( fx.prop !== "height" ) {
|
||||
if ( boxSizing === "content-box" ) {
|
||||
adjust += fx.now;
|
||||
}
|
||||
} else if ( that.options.heightStyle !== "content" ) {
|
||||
fx.now = Math.round( total - toHide.outerHeight() - adjust );
|
||||
adjust = 0;
|
||||
}
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_toggleComplete: function( data ) {
|
||||
var toHide = data.oldPanel,
|
||||
prev = toHide.prev();
|
||||
|
||||
this._removeClass( toHide, "ui-accordion-content-active" );
|
||||
this._removeClass( prev, "ui-accordion-header-active" )
|
||||
._addClass( prev, "ui-accordion-header-collapsed" );
|
||||
|
||||
// Work around for rendering bug in IE (#5421)
|
||||
if ( toHide.length ) {
|
||||
toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
|
||||
}
|
||||
this._trigger( "activate", null, data );
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
File diff suppressed because one or more lines are too long
+674
@@ -0,0 +1,674 @@
|
||||
/*!
|
||||
* jQuery UI Autocomplete 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Autocomplete
|
||||
//>>group: Widgets
|
||||
//>>description: Lists suggested words as the user is typing.
|
||||
//>>docs: http://api.jqueryui.com/autocomplete/
|
||||
//>>demos: http://jqueryui.com/autocomplete/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/autocomplete.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./menu",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.widget( "ui.autocomplete", {
|
||||
version: "1.13.2",
|
||||
defaultElement: "<input>",
|
||||
options: {
|
||||
appendTo: null,
|
||||
autoFocus: false,
|
||||
delay: 300,
|
||||
minLength: 1,
|
||||
position: {
|
||||
my: "left top",
|
||||
at: "left bottom",
|
||||
collision: "none"
|
||||
},
|
||||
source: null,
|
||||
|
||||
// Callbacks
|
||||
change: null,
|
||||
close: null,
|
||||
focus: null,
|
||||
open: null,
|
||||
response: null,
|
||||
search: null,
|
||||
select: null
|
||||
},
|
||||
|
||||
requestIndex: 0,
|
||||
pending: 0,
|
||||
liveRegionTimer: null,
|
||||
|
||||
_create: function() {
|
||||
|
||||
// Some browsers only repeat keydown events, not keypress events,
|
||||
// so we use the suppressKeyPress flag to determine if we've already
|
||||
// handled the keydown event. #7269
|
||||
// Unfortunately the code for & in keypress is the same as the up arrow,
|
||||
// so we use the suppressKeyPressRepeat flag to avoid handling keypress
|
||||
// events when we know the keydown event was used to modify the
|
||||
// search term. #7799
|
||||
var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
|
||||
nodeName = this.element[ 0 ].nodeName.toLowerCase(),
|
||||
isTextarea = nodeName === "textarea",
|
||||
isInput = nodeName === "input";
|
||||
|
||||
// Textareas are always multi-line
|
||||
// Inputs are always single-line, even if inside a contentEditable element
|
||||
// IE also treats inputs as contentEditable
|
||||
// All other element types are determined by whether or not they're contentEditable
|
||||
this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
|
||||
|
||||
this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
|
||||
this.isNewMenu = true;
|
||||
|
||||
this._addClass( "ui-autocomplete-input" );
|
||||
this.element.attr( "autocomplete", "off" );
|
||||
|
||||
this._on( this.element, {
|
||||
keydown: function( event ) {
|
||||
if ( this.element.prop( "readOnly" ) ) {
|
||||
suppressKeyPress = true;
|
||||
suppressInput = true;
|
||||
suppressKeyPressRepeat = true;
|
||||
return;
|
||||
}
|
||||
|
||||
suppressKeyPress = false;
|
||||
suppressInput = false;
|
||||
suppressKeyPressRepeat = false;
|
||||
var keyCode = $.ui.keyCode;
|
||||
switch ( event.keyCode ) {
|
||||
case keyCode.PAGE_UP:
|
||||
suppressKeyPress = true;
|
||||
this._move( "previousPage", event );
|
||||
break;
|
||||
case keyCode.PAGE_DOWN:
|
||||
suppressKeyPress = true;
|
||||
this._move( "nextPage", event );
|
||||
break;
|
||||
case keyCode.UP:
|
||||
suppressKeyPress = true;
|
||||
this._keyEvent( "previous", event );
|
||||
break;
|
||||
case keyCode.DOWN:
|
||||
suppressKeyPress = true;
|
||||
this._keyEvent( "next", event );
|
||||
break;
|
||||
case keyCode.ENTER:
|
||||
|
||||
// when menu is open and has focus
|
||||
if ( this.menu.active ) {
|
||||
|
||||
// #6055 - Opera still allows the keypress to occur
|
||||
// which causes forms to submit
|
||||
suppressKeyPress = true;
|
||||
event.preventDefault();
|
||||
this.menu.select( event );
|
||||
}
|
||||
break;
|
||||
case keyCode.TAB:
|
||||
if ( this.menu.active ) {
|
||||
this.menu.select( event );
|
||||
}
|
||||
break;
|
||||
case keyCode.ESCAPE:
|
||||
if ( this.menu.element.is( ":visible" ) ) {
|
||||
if ( !this.isMultiLine ) {
|
||||
this._value( this.term );
|
||||
}
|
||||
this.close( event );
|
||||
|
||||
// Different browsers have different default behavior for escape
|
||||
// Single press can mean undo or clear
|
||||
// Double press in IE means clear the whole form
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
suppressKeyPressRepeat = true;
|
||||
|
||||
// search timeout should be triggered before the input value is changed
|
||||
this._searchTimeout( event );
|
||||
break;
|
||||
}
|
||||
},
|
||||
keypress: function( event ) {
|
||||
if ( suppressKeyPress ) {
|
||||
suppressKeyPress = false;
|
||||
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
|
||||
event.preventDefault();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ( suppressKeyPressRepeat ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Replicate some key handlers to allow them to repeat in Firefox and Opera
|
||||
var keyCode = $.ui.keyCode;
|
||||
switch ( event.keyCode ) {
|
||||
case keyCode.PAGE_UP:
|
||||
this._move( "previousPage", event );
|
||||
break;
|
||||
case keyCode.PAGE_DOWN:
|
||||
this._move( "nextPage", event );
|
||||
break;
|
||||
case keyCode.UP:
|
||||
this._keyEvent( "previous", event );
|
||||
break;
|
||||
case keyCode.DOWN:
|
||||
this._keyEvent( "next", event );
|
||||
break;
|
||||
}
|
||||
},
|
||||
input: function( event ) {
|
||||
if ( suppressInput ) {
|
||||
suppressInput = false;
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
this._searchTimeout( event );
|
||||
},
|
||||
focus: function() {
|
||||
this.selectedItem = null;
|
||||
this.previous = this._value();
|
||||
},
|
||||
blur: function( event ) {
|
||||
clearTimeout( this.searching );
|
||||
this.close( event );
|
||||
this._change( event );
|
||||
}
|
||||
} );
|
||||
|
||||
this._initSource();
|
||||
this.menu = $( "<ul>" )
|
||||
.appendTo( this._appendTo() )
|
||||
.menu( {
|
||||
|
||||
// disable ARIA support, the live region takes care of that
|
||||
role: null
|
||||
} )
|
||||
.hide()
|
||||
|
||||
// Support: IE 11 only, Edge <= 14
|
||||
// For other browsers, we preventDefault() on the mousedown event
|
||||
// to keep the dropdown from taking focus from the input. This doesn't
|
||||
// work for IE/Edge, causing problems with selection and scrolling (#9638)
|
||||
// Happily, IE and Edge support an "unselectable" attribute that
|
||||
// prevents an element from receiving focus, exactly what we want here.
|
||||
.attr( {
|
||||
"unselectable": "on"
|
||||
} )
|
||||
.menu( "instance" );
|
||||
|
||||
this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
|
||||
this._on( this.menu.element, {
|
||||
mousedown: function( event ) {
|
||||
|
||||
// Prevent moving focus out of the text field
|
||||
event.preventDefault();
|
||||
},
|
||||
menufocus: function( event, ui ) {
|
||||
var label, item;
|
||||
|
||||
// support: Firefox
|
||||
// Prevent accidental activation of menu items in Firefox (#7024 #9118)
|
||||
if ( this.isNewMenu ) {
|
||||
this.isNewMenu = false;
|
||||
if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
|
||||
this.menu.blur();
|
||||
|
||||
this.document.one( "mousemove", function() {
|
||||
$( event.target ).trigger( event.originalEvent );
|
||||
} );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item = ui.item.data( "ui-autocomplete-item" );
|
||||
if ( false !== this._trigger( "focus", event, { item: item } ) ) {
|
||||
|
||||
// use value to match what will end up in the input, if it was a key event
|
||||
if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
|
||||
this._value( item.value );
|
||||
}
|
||||
}
|
||||
|
||||
// Announce the value in the liveRegion
|
||||
label = ui.item.attr( "aria-label" ) || item.value;
|
||||
if ( label && String.prototype.trim.call( label ).length ) {
|
||||
clearTimeout( this.liveRegionTimer );
|
||||
this.liveRegionTimer = this._delay( function() {
|
||||
this.liveRegion.html( $( "<div>" ).text( label ) );
|
||||
}, 100 );
|
||||
}
|
||||
},
|
||||
menuselect: function( event, ui ) {
|
||||
var item = ui.item.data( "ui-autocomplete-item" ),
|
||||
previous = this.previous;
|
||||
|
||||
// Only trigger when focus was lost (click on menu)
|
||||
if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
|
||||
this.element.trigger( "focus" );
|
||||
this.previous = previous;
|
||||
|
||||
// #6109 - IE triggers two focus events and the second
|
||||
// is asynchronous, so we need to reset the previous
|
||||
// term synchronously and asynchronously :-(
|
||||
this._delay( function() {
|
||||
this.previous = previous;
|
||||
this.selectedItem = item;
|
||||
} );
|
||||
}
|
||||
|
||||
if ( false !== this._trigger( "select", event, { item: item } ) ) {
|
||||
this._value( item.value );
|
||||
}
|
||||
|
||||
// reset the term after the select event
|
||||
// this allows custom select handling to work properly
|
||||
this.term = this._value();
|
||||
|
||||
this.close( event );
|
||||
this.selectedItem = item;
|
||||
}
|
||||
} );
|
||||
|
||||
this.liveRegion = $( "<div>", {
|
||||
role: "status",
|
||||
"aria-live": "assertive",
|
||||
"aria-relevant": "additions"
|
||||
} )
|
||||
.appendTo( this.document[ 0 ].body );
|
||||
|
||||
this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
|
||||
|
||||
// Turning off autocomplete prevents the browser from remembering the
|
||||
// value when navigating through history, so we re-enable autocomplete
|
||||
// if the page is unloaded before the widget is destroyed. #7790
|
||||
this._on( this.window, {
|
||||
beforeunload: function() {
|
||||
this.element.removeAttr( "autocomplete" );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
clearTimeout( this.searching );
|
||||
this.element.removeAttr( "autocomplete" );
|
||||
this.menu.element.remove();
|
||||
this.liveRegion.remove();
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
this._super( key, value );
|
||||
if ( key === "source" ) {
|
||||
this._initSource();
|
||||
}
|
||||
if ( key === "appendTo" ) {
|
||||
this.menu.element.appendTo( this._appendTo() );
|
||||
}
|
||||
if ( key === "disabled" && value && this.xhr ) {
|
||||
this.xhr.abort();
|
||||
}
|
||||
},
|
||||
|
||||
_isEventTargetInWidget: function( event ) {
|
||||
var menuElement = this.menu.element[ 0 ];
|
||||
|
||||
return event.target === this.element[ 0 ] ||
|
||||
event.target === menuElement ||
|
||||
$.contains( menuElement, event.target );
|
||||
},
|
||||
|
||||
_closeOnClickOutside: function( event ) {
|
||||
if ( !this._isEventTargetInWidget( event ) ) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
_appendTo: function() {
|
||||
var element = this.options.appendTo;
|
||||
|
||||
if ( element ) {
|
||||
element = element.jquery || element.nodeType ?
|
||||
$( element ) :
|
||||
this.document.find( element ).eq( 0 );
|
||||
}
|
||||
|
||||
if ( !element || !element[ 0 ] ) {
|
||||
element = this.element.closest( ".ui-front, dialog" );
|
||||
}
|
||||
|
||||
if ( !element.length ) {
|
||||
element = this.document[ 0 ].body;
|
||||
}
|
||||
|
||||
return element;
|
||||
},
|
||||
|
||||
_initSource: function() {
|
||||
var array, url,
|
||||
that = this;
|
||||
if ( Array.isArray( this.options.source ) ) {
|
||||
array = this.options.source;
|
||||
this.source = function( request, response ) {
|
||||
response( $.ui.autocomplete.filter( array, request.term ) );
|
||||
};
|
||||
} else if ( typeof this.options.source === "string" ) {
|
||||
url = this.options.source;
|
||||
this.source = function( request, response ) {
|
||||
if ( that.xhr ) {
|
||||
that.xhr.abort();
|
||||
}
|
||||
that.xhr = $.ajax( {
|
||||
url: url,
|
||||
data: request,
|
||||
dataType: "json",
|
||||
success: function( data ) {
|
||||
response( data );
|
||||
},
|
||||
error: function() {
|
||||
response( [] );
|
||||
}
|
||||
} );
|
||||
};
|
||||
} else {
|
||||
this.source = this.options.source;
|
||||
}
|
||||
},
|
||||
|
||||
_searchTimeout: function( event ) {
|
||||
clearTimeout( this.searching );
|
||||
this.searching = this._delay( function() {
|
||||
|
||||
// Search if the value has changed, or if the user retypes the same value (see #7434)
|
||||
var equalValues = this.term === this._value(),
|
||||
menuVisible = this.menu.element.is( ":visible" ),
|
||||
modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
||||
|
||||
if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
|
||||
this.selectedItem = null;
|
||||
this.search( null, event );
|
||||
}
|
||||
}, this.options.delay );
|
||||
},
|
||||
|
||||
search: function( value, event ) {
|
||||
value = value != null ? value : this._value();
|
||||
|
||||
// Always save the actual value, not the one passed as an argument
|
||||
this.term = this._value();
|
||||
|
||||
if ( value.length < this.options.minLength ) {
|
||||
return this.close( event );
|
||||
}
|
||||
|
||||
if ( this._trigger( "search", event ) === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._search( value );
|
||||
},
|
||||
|
||||
_search: function( value ) {
|
||||
this.pending++;
|
||||
this._addClass( "ui-autocomplete-loading" );
|
||||
this.cancelSearch = false;
|
||||
|
||||
this.source( { term: value }, this._response() );
|
||||
},
|
||||
|
||||
_response: function() {
|
||||
var index = ++this.requestIndex;
|
||||
|
||||
return function( content ) {
|
||||
if ( index === this.requestIndex ) {
|
||||
this.__response( content );
|
||||
}
|
||||
|
||||
this.pending--;
|
||||
if ( !this.pending ) {
|
||||
this._removeClass( "ui-autocomplete-loading" );
|
||||
}
|
||||
}.bind( this );
|
||||
},
|
||||
|
||||
__response: function( content ) {
|
||||
if ( content ) {
|
||||
content = this._normalize( content );
|
||||
}
|
||||
this._trigger( "response", null, { content: content } );
|
||||
if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
|
||||
this._suggest( content );
|
||||
this._trigger( "open" );
|
||||
} else {
|
||||
|
||||
// use ._close() instead of .close() so we don't cancel future searches
|
||||
this._close();
|
||||
}
|
||||
},
|
||||
|
||||
close: function( event ) {
|
||||
this.cancelSearch = true;
|
||||
this._close( event );
|
||||
},
|
||||
|
||||
_close: function( event ) {
|
||||
|
||||
// Remove the handler that closes the menu on outside clicks
|
||||
this._off( this.document, "mousedown" );
|
||||
|
||||
if ( this.menu.element.is( ":visible" ) ) {
|
||||
this.menu.element.hide();
|
||||
this.menu.blur();
|
||||
this.isNewMenu = true;
|
||||
this._trigger( "close", event );
|
||||
}
|
||||
},
|
||||
|
||||
_change: function( event ) {
|
||||
if ( this.previous !== this._value() ) {
|
||||
this._trigger( "change", event, { item: this.selectedItem } );
|
||||
}
|
||||
},
|
||||
|
||||
_normalize: function( items ) {
|
||||
|
||||
// assume all items have the right format when the first item is complete
|
||||
if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
|
||||
return items;
|
||||
}
|
||||
return $.map( items, function( item ) {
|
||||
if ( typeof item === "string" ) {
|
||||
return {
|
||||
label: item,
|
||||
value: item
|
||||
};
|
||||
}
|
||||
return $.extend( {}, item, {
|
||||
label: item.label || item.value,
|
||||
value: item.value || item.label
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
_suggest: function( items ) {
|
||||
var ul = this.menu.element.empty();
|
||||
this._renderMenu( ul, items );
|
||||
this.isNewMenu = true;
|
||||
this.menu.refresh();
|
||||
|
||||
// Size and position menu
|
||||
ul.show();
|
||||
this._resizeMenu();
|
||||
ul.position( $.extend( {
|
||||
of: this.element
|
||||
}, this.options.position ) );
|
||||
|
||||
if ( this.options.autoFocus ) {
|
||||
this.menu.next();
|
||||
}
|
||||
|
||||
// Listen for interactions outside of the widget (#6642)
|
||||
this._on( this.document, {
|
||||
mousedown: "_closeOnClickOutside"
|
||||
} );
|
||||
},
|
||||
|
||||
_resizeMenu: function() {
|
||||
var ul = this.menu.element;
|
||||
ul.outerWidth( Math.max(
|
||||
|
||||
// Firefox wraps long text (possibly a rounding bug)
|
||||
// so we add 1px to avoid the wrapping (#7513)
|
||||
ul.width( "" ).outerWidth() + 1,
|
||||
this.element.outerWidth()
|
||||
) );
|
||||
},
|
||||
|
||||
_renderMenu: function( ul, items ) {
|
||||
var that = this;
|
||||
$.each( items, function( index, item ) {
|
||||
that._renderItemData( ul, item );
|
||||
} );
|
||||
},
|
||||
|
||||
_renderItemData: function( ul, item ) {
|
||||
return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
|
||||
},
|
||||
|
||||
_renderItem: function( ul, item ) {
|
||||
return $( "<li>" )
|
||||
.append( $( "<div>" ).text( item.label ) )
|
||||
.appendTo( ul );
|
||||
},
|
||||
|
||||
_move: function( direction, event ) {
|
||||
if ( !this.menu.element.is( ":visible" ) ) {
|
||||
this.search( null, event );
|
||||
return;
|
||||
}
|
||||
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
|
||||
this.menu.isLastItem() && /^next/.test( direction ) ) {
|
||||
|
||||
if ( !this.isMultiLine ) {
|
||||
this._value( this.term );
|
||||
}
|
||||
|
||||
this.menu.blur();
|
||||
return;
|
||||
}
|
||||
this.menu[ direction ]( event );
|
||||
},
|
||||
|
||||
widget: function() {
|
||||
return this.menu.element;
|
||||
},
|
||||
|
||||
_value: function() {
|
||||
return this.valueMethod.apply( this.element, arguments );
|
||||
},
|
||||
|
||||
_keyEvent: function( keyEvent, event ) {
|
||||
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
|
||||
this._move( keyEvent, event );
|
||||
|
||||
// Prevents moving cursor to beginning/end of the text field in some browsers
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
// Support: Chrome <=50
|
||||
// We should be able to just use this.element.prop( "isContentEditable" )
|
||||
// but hidden elements always report false in Chrome.
|
||||
// https://code.google.com/p/chromium/issues/detail?id=313082
|
||||
_isContentEditable: function( element ) {
|
||||
if ( !element.length ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var editable = element.prop( "contentEditable" );
|
||||
|
||||
if ( editable === "inherit" ) {
|
||||
return this._isContentEditable( element.parent() );
|
||||
}
|
||||
|
||||
return editable === "true";
|
||||
}
|
||||
} );
|
||||
|
||||
$.extend( $.ui.autocomplete, {
|
||||
escapeRegex: function( value ) {
|
||||
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
|
||||
},
|
||||
filter: function( array, term ) {
|
||||
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
|
||||
return $.grep( array, function( value ) {
|
||||
return matcher.test( value.label || value.value || value );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
// Live region extension, adding a `messages` option
|
||||
// NOTE: This is an experimental API. We are still investigating
|
||||
// a full solution for string manipulation and internationalization.
|
||||
$.widget( "ui.autocomplete", $.ui.autocomplete, {
|
||||
options: {
|
||||
messages: {
|
||||
noResults: "No search results.",
|
||||
results: function( amount ) {
|
||||
return amount + ( amount > 1 ? " results are" : " result is" ) +
|
||||
" available, use up and down arrow keys to navigate.";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
__response: function( content ) {
|
||||
var message;
|
||||
this._superApply( arguments );
|
||||
if ( this.options.disabled || this.cancelSearch ) {
|
||||
return;
|
||||
}
|
||||
if ( content && content.length ) {
|
||||
message = this.options.messages.results( content.length );
|
||||
} else {
|
||||
message = this.options.messages.noResults;
|
||||
}
|
||||
clearTimeout( this.liveRegionTimer );
|
||||
this.liveRegionTimer = this._delay( function() {
|
||||
this.liveRegion.html( $( "<div>" ).text( message ) );
|
||||
}, 100 );
|
||||
}
|
||||
} );
|
||||
|
||||
return $.ui.autocomplete;
|
||||
|
||||
} );
|
||||
File diff suppressed because one or more lines are too long
+448
@@ -0,0 +1,448 @@
|
||||
/*!
|
||||
* jQuery UI Button 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Button
|
||||
//>>group: Widgets
|
||||
//>>description: Enhances a form with themeable buttons.
|
||||
//>>docs: http://api.jqueryui.com/button/
|
||||
//>>demos: http://jqueryui.com/button/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/button.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
|
||||
// These are only for backcompat
|
||||
// TODO: Remove after 1.12
|
||||
"./controlgroup",
|
||||
"./checkboxradio",
|
||||
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.widget( "ui.button", {
|
||||
version: "1.13.2",
|
||||
defaultElement: "<button>",
|
||||
options: {
|
||||
classes: {
|
||||
"ui-button": "ui-corner-all"
|
||||
},
|
||||
disabled: null,
|
||||
icon: null,
|
||||
iconPosition: "beginning",
|
||||
label: null,
|
||||
showLabel: true
|
||||
},
|
||||
|
||||
_getCreateOptions: function() {
|
||||
var disabled,
|
||||
|
||||
// This is to support cases like in jQuery Mobile where the base widget does have
|
||||
// an implementation of _getCreateOptions
|
||||
options = this._super() || {};
|
||||
|
||||
this.isInput = this.element.is( "input" );
|
||||
|
||||
disabled = this.element[ 0 ].disabled;
|
||||
if ( disabled != null ) {
|
||||
options.disabled = disabled;
|
||||
}
|
||||
|
||||
this.originalLabel = this.isInput ? this.element.val() : this.element.html();
|
||||
if ( this.originalLabel ) {
|
||||
options.label = this.originalLabel;
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
if ( !this.option.showLabel & !this.options.icon ) {
|
||||
this.options.showLabel = true;
|
||||
}
|
||||
|
||||
// We have to check the option again here even though we did in _getCreateOptions,
|
||||
// because null may have been passed on init which would override what was set in
|
||||
// _getCreateOptions
|
||||
if ( this.options.disabled == null ) {
|
||||
this.options.disabled = this.element[ 0 ].disabled || false;
|
||||
}
|
||||
|
||||
this.hasTitle = !!this.element.attr( "title" );
|
||||
|
||||
// Check to see if the label needs to be set or if its already correct
|
||||
if ( this.options.label && this.options.label !== this.originalLabel ) {
|
||||
if ( this.isInput ) {
|
||||
this.element.val( this.options.label );
|
||||
} else {
|
||||
this.element.html( this.options.label );
|
||||
}
|
||||
}
|
||||
this._addClass( "ui-button", "ui-widget" );
|
||||
this._setOption( "disabled", this.options.disabled );
|
||||
this._enhance();
|
||||
|
||||
if ( this.element.is( "a" ) ) {
|
||||
this._on( {
|
||||
"keyup": function( event ) {
|
||||
if ( event.keyCode === $.ui.keyCode.SPACE ) {
|
||||
event.preventDefault();
|
||||
|
||||
// Support: PhantomJS <= 1.9, IE 8 Only
|
||||
// If a native click is available use it so we actually cause navigation
|
||||
// otherwise just trigger a click event
|
||||
if ( this.element[ 0 ].click ) {
|
||||
this.element[ 0 ].click();
|
||||
} else {
|
||||
this.element.trigger( "click" );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
_enhance: function() {
|
||||
if ( !this.element.is( "button" ) ) {
|
||||
this.element.attr( "role", "button" );
|
||||
}
|
||||
|
||||
if ( this.options.icon ) {
|
||||
this._updateIcon( "icon", this.options.icon );
|
||||
this._updateTooltip();
|
||||
}
|
||||
},
|
||||
|
||||
_updateTooltip: function() {
|
||||
this.title = this.element.attr( "title" );
|
||||
|
||||
if ( !this.options.showLabel && !this.title ) {
|
||||
this.element.attr( "title", this.options.label );
|
||||
}
|
||||
},
|
||||
|
||||
_updateIcon: function( option, value ) {
|
||||
var icon = option !== "iconPosition",
|
||||
position = icon ? this.options.iconPosition : value,
|
||||
displayBlock = position === "top" || position === "bottom";
|
||||
|
||||
// Create icon
|
||||
if ( !this.icon ) {
|
||||
this.icon = $( "<span>" );
|
||||
|
||||
this._addClass( this.icon, "ui-button-icon", "ui-icon" );
|
||||
|
||||
if ( !this.options.showLabel ) {
|
||||
this._addClass( "ui-button-icon-only" );
|
||||
}
|
||||
} else if ( icon ) {
|
||||
|
||||
// If we are updating the icon remove the old icon class
|
||||
this._removeClass( this.icon, null, this.options.icon );
|
||||
}
|
||||
|
||||
// If we are updating the icon add the new icon class
|
||||
if ( icon ) {
|
||||
this._addClass( this.icon, null, value );
|
||||
}
|
||||
|
||||
this._attachIcon( position );
|
||||
|
||||
// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
|
||||
// the iconSpace if there is one.
|
||||
if ( displayBlock ) {
|
||||
this._addClass( this.icon, null, "ui-widget-icon-block" );
|
||||
if ( this.iconSpace ) {
|
||||
this.iconSpace.remove();
|
||||
}
|
||||
} else {
|
||||
|
||||
// Position is beginning or end so remove the ui-widget-icon-block class and add the
|
||||
// space if it does not exist
|
||||
if ( !this.iconSpace ) {
|
||||
this.iconSpace = $( "<span> </span>" );
|
||||
this._addClass( this.iconSpace, "ui-button-icon-space" );
|
||||
}
|
||||
this._removeClass( this.icon, null, "ui-wiget-icon-block" );
|
||||
this._attachIconSpace( position );
|
||||
}
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
this.element.removeAttr( "role" );
|
||||
|
||||
if ( this.icon ) {
|
||||
this.icon.remove();
|
||||
}
|
||||
if ( this.iconSpace ) {
|
||||
this.iconSpace.remove();
|
||||
}
|
||||
if ( !this.hasTitle ) {
|
||||
this.element.removeAttr( "title" );
|
||||
}
|
||||
},
|
||||
|
||||
_attachIconSpace: function( iconPosition ) {
|
||||
this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
|
||||
},
|
||||
|
||||
_attachIcon: function( iconPosition ) {
|
||||
this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
|
||||
},
|
||||
|
||||
_setOptions: function( options ) {
|
||||
var newShowLabel = options.showLabel === undefined ?
|
||||
this.options.showLabel :
|
||||
options.showLabel,
|
||||
newIcon = options.icon === undefined ? this.options.icon : options.icon;
|
||||
|
||||
if ( !newShowLabel && !newIcon ) {
|
||||
options.showLabel = true;
|
||||
}
|
||||
this._super( options );
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
if ( key === "icon" ) {
|
||||
if ( value ) {
|
||||
this._updateIcon( key, value );
|
||||
} else if ( this.icon ) {
|
||||
this.icon.remove();
|
||||
if ( this.iconSpace ) {
|
||||
this.iconSpace.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( key === "iconPosition" ) {
|
||||
this._updateIcon( key, value );
|
||||
}
|
||||
|
||||
// Make sure we can't end up with a button that has neither text nor icon
|
||||
if ( key === "showLabel" ) {
|
||||
this._toggleClass( "ui-button-icon-only", null, !value );
|
||||
this._updateTooltip();
|
||||
}
|
||||
|
||||
if ( key === "label" ) {
|
||||
if ( this.isInput ) {
|
||||
this.element.val( value );
|
||||
} else {
|
||||
|
||||
// If there is an icon, append it, else nothing then append the value
|
||||
// this avoids removal of the icon when setting label text
|
||||
this.element.html( value );
|
||||
if ( this.icon ) {
|
||||
this._attachIcon( this.options.iconPosition );
|
||||
this._attachIconSpace( this.options.iconPosition );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this._toggleClass( null, "ui-state-disabled", value );
|
||||
this.element[ 0 ].disabled = value;
|
||||
if ( value ) {
|
||||
this.element.trigger( "blur" );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
|
||||
// Make sure to only check disabled if its an element that supports this otherwise
|
||||
// check for the disabled class to determine state
|
||||
var isDisabled = this.element.is( "input, button" ) ?
|
||||
this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
|
||||
|
||||
if ( isDisabled !== this.options.disabled ) {
|
||||
this._setOptions( { disabled: isDisabled } );
|
||||
}
|
||||
|
||||
this._updateTooltip();
|
||||
}
|
||||
} );
|
||||
|
||||
// DEPRECATED
|
||||
if ( $.uiBackCompat !== false ) {
|
||||
|
||||
// Text and Icons options
|
||||
$.widget( "ui.button", $.ui.button, {
|
||||
options: {
|
||||
text: true,
|
||||
icons: {
|
||||
primary: null,
|
||||
secondary: null
|
||||
}
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
if ( this.options.showLabel && !this.options.text ) {
|
||||
this.options.showLabel = this.options.text;
|
||||
}
|
||||
if ( !this.options.showLabel && this.options.text ) {
|
||||
this.options.text = this.options.showLabel;
|
||||
}
|
||||
if ( !this.options.icon && ( this.options.icons.primary ||
|
||||
this.options.icons.secondary ) ) {
|
||||
if ( this.options.icons.primary ) {
|
||||
this.options.icon = this.options.icons.primary;
|
||||
} else {
|
||||
this.options.icon = this.options.icons.secondary;
|
||||
this.options.iconPosition = "end";
|
||||
}
|
||||
} else if ( this.options.icon ) {
|
||||
this.options.icons.primary = this.options.icon;
|
||||
}
|
||||
this._super();
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
if ( key === "text" ) {
|
||||
this._super( "showLabel", value );
|
||||
return;
|
||||
}
|
||||
if ( key === "showLabel" ) {
|
||||
this.options.text = value;
|
||||
}
|
||||
if ( key === "icon" ) {
|
||||
this.options.icons.primary = value;
|
||||
}
|
||||
if ( key === "icons" ) {
|
||||
if ( value.primary ) {
|
||||
this._super( "icon", value.primary );
|
||||
this._super( "iconPosition", "beginning" );
|
||||
} else if ( value.secondary ) {
|
||||
this._super( "icon", value.secondary );
|
||||
this._super( "iconPosition", "end" );
|
||||
}
|
||||
}
|
||||
this._superApply( arguments );
|
||||
}
|
||||
} );
|
||||
|
||||
$.fn.button = ( function( orig ) {
|
||||
return function( options ) {
|
||||
var isMethodCall = typeof options === "string";
|
||||
var args = Array.prototype.slice.call( arguments, 1 );
|
||||
var returnValue = this;
|
||||
|
||||
if ( isMethodCall ) {
|
||||
|
||||
// If this is an empty collection, we need to have the instance method
|
||||
// return undefined instead of the jQuery instance
|
||||
if ( !this.length && options === "instance" ) {
|
||||
returnValue = undefined;
|
||||
} else {
|
||||
this.each( function() {
|
||||
var methodValue;
|
||||
var type = $( this ).attr( "type" );
|
||||
var name = type !== "checkbox" && type !== "radio" ?
|
||||
"button" :
|
||||
"checkboxradio";
|
||||
var instance = $.data( this, "ui-" + name );
|
||||
|
||||
if ( options === "instance" ) {
|
||||
returnValue = instance;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on button" +
|
||||
" prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
|
||||
if ( typeof instance[ options ] !== "function" ||
|
||||
options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for button" +
|
||||
" widget instance" );
|
||||
}
|
||||
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
} else {
|
||||
|
||||
// Allow multiple hashes to be passed on init
|
||||
if ( args.length ) {
|
||||
options = $.widget.extend.apply( null, [ options ].concat( args ) );
|
||||
}
|
||||
|
||||
this.each( function() {
|
||||
var type = $( this ).attr( "type" );
|
||||
var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
|
||||
var instance = $.data( this, "ui-" + name );
|
||||
|
||||
if ( instance ) {
|
||||
instance.option( options || {} );
|
||||
if ( instance._init ) {
|
||||
instance._init();
|
||||
}
|
||||
} else {
|
||||
if ( name === "button" ) {
|
||||
orig.call( $( this ), options );
|
||||
return;
|
||||
}
|
||||
|
||||
$( this ).checkboxradio( $.extend( { icon: false }, options ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
} )( $.fn.button );
|
||||
|
||||
$.fn.buttonset = function() {
|
||||
if ( !$.ui.controlgroup ) {
|
||||
$.error( "Controlgroup widget missing" );
|
||||
}
|
||||
if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
|
||||
return this.controlgroup.apply( this,
|
||||
[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
|
||||
}
|
||||
if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
|
||||
return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
|
||||
}
|
||||
if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
|
||||
arguments[ 0 ].items = {
|
||||
button: arguments[ 0 ].items
|
||||
};
|
||||
}
|
||||
return this.controlgroup.apply( this, arguments );
|
||||
};
|
||||
}
|
||||
|
||||
return $.ui.button;
|
||||
|
||||
} );
|
||||
File diff suppressed because one or more lines are too long
+288
@@ -0,0 +1,288 @@
|
||||
/*!
|
||||
* jQuery UI Checkboxradio 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Checkboxradio
|
||||
//>>group: Widgets
|
||||
//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
|
||||
//>>docs: http://api.jqueryui.com/checkboxradio/
|
||||
//>>demos: http://jqueryui.com/checkboxradio/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/button.css
|
||||
//>>css.structure: ../../themes/base/checkboxradio.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
|
||||
version: "1.13.2",
|
||||
options: {
|
||||
disabled: null,
|
||||
label: null,
|
||||
icon: true,
|
||||
classes: {
|
||||
"ui-checkboxradio-label": "ui-corner-all",
|
||||
"ui-checkboxradio-icon": "ui-corner-all"
|
||||
}
|
||||
},
|
||||
|
||||
_getCreateOptions: function() {
|
||||
var disabled, labels, labelContents;
|
||||
var options = this._super() || {};
|
||||
|
||||
// We read the type here, because it makes more sense to throw a element type error first,
|
||||
// rather then the error for lack of a label. Often if its the wrong type, it
|
||||
// won't have a label (e.g. calling on a div, btn, etc)
|
||||
this._readType();
|
||||
|
||||
labels = this.element.labels();
|
||||
|
||||
// If there are multiple labels, use the last one
|
||||
this.label = $( labels[ labels.length - 1 ] );
|
||||
if ( !this.label.length ) {
|
||||
$.error( "No label found for checkboxradio widget" );
|
||||
}
|
||||
|
||||
this.originalLabel = "";
|
||||
|
||||
// We need to get the label text but this may also need to make sure it does not contain the
|
||||
// input itself.
|
||||
// The label contents could be text, html, or a mix. We wrap all elements
|
||||
// and read the wrapper's `innerHTML` to get a string representation of
|
||||
// the label, without the input as part of it.
|
||||
labelContents = this.label.contents().not( this.element[ 0 ] );
|
||||
|
||||
if ( labelContents.length ) {
|
||||
this.originalLabel += labelContents
|
||||
.clone()
|
||||
.wrapAll( "<div></div>" )
|
||||
.parent()
|
||||
.html();
|
||||
}
|
||||
|
||||
// Set the label option if we found label text
|
||||
if ( this.originalLabel ) {
|
||||
options.label = this.originalLabel;
|
||||
}
|
||||
|
||||
disabled = this.element[ 0 ].disabled;
|
||||
if ( disabled != null ) {
|
||||
options.disabled = disabled;
|
||||
}
|
||||
return options;
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
var checked = this.element[ 0 ].checked;
|
||||
|
||||
this._bindFormResetHandler();
|
||||
|
||||
if ( this.options.disabled == null ) {
|
||||
this.options.disabled = this.element[ 0 ].disabled;
|
||||
}
|
||||
|
||||
this._setOption( "disabled", this.options.disabled );
|
||||
this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
|
||||
this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
|
||||
|
||||
if ( this.type === "radio" ) {
|
||||
this._addClass( this.label, "ui-checkboxradio-radio-label" );
|
||||
}
|
||||
|
||||
if ( this.options.label && this.options.label !== this.originalLabel ) {
|
||||
this._updateLabel();
|
||||
} else if ( this.originalLabel ) {
|
||||
this.options.label = this.originalLabel;
|
||||
}
|
||||
|
||||
this._enhance();
|
||||
|
||||
if ( checked ) {
|
||||
this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
|
||||
}
|
||||
|
||||
this._on( {
|
||||
change: "_toggleClasses",
|
||||
focus: function() {
|
||||
this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
|
||||
},
|
||||
blur: function() {
|
||||
this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_readType: function() {
|
||||
var nodeName = this.element[ 0 ].nodeName.toLowerCase();
|
||||
this.type = this.element[ 0 ].type;
|
||||
if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
|
||||
$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
|
||||
" and element.type=" + this.type );
|
||||
}
|
||||
},
|
||||
|
||||
// Support jQuery Mobile enhanced option
|
||||
_enhance: function() {
|
||||
this._updateIcon( this.element[ 0 ].checked );
|
||||
},
|
||||
|
||||
widget: function() {
|
||||
return this.label;
|
||||
},
|
||||
|
||||
_getRadioGroup: function() {
|
||||
var group;
|
||||
var name = this.element[ 0 ].name;
|
||||
var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
|
||||
|
||||
if ( !name ) {
|
||||
return $( [] );
|
||||
}
|
||||
|
||||
if ( this.form.length ) {
|
||||
group = $( this.form[ 0 ].elements ).filter( nameSelector );
|
||||
} else {
|
||||
|
||||
// Not inside a form, check all inputs that also are not inside a form
|
||||
group = $( nameSelector ).filter( function() {
|
||||
return $( this )._form().length === 0;
|
||||
} );
|
||||
}
|
||||
|
||||
return group.not( this.element );
|
||||
},
|
||||
|
||||
_toggleClasses: function() {
|
||||
var checked = this.element[ 0 ].checked;
|
||||
this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
|
||||
|
||||
if ( this.options.icon && this.type === "checkbox" ) {
|
||||
this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
|
||||
._toggleClass( this.icon, null, "ui-icon-blank", !checked );
|
||||
}
|
||||
|
||||
if ( this.type === "radio" ) {
|
||||
this._getRadioGroup()
|
||||
.each( function() {
|
||||
var instance = $( this ).checkboxradio( "instance" );
|
||||
|
||||
if ( instance ) {
|
||||
instance._removeClass( instance.label,
|
||||
"ui-checkboxradio-checked", "ui-state-active" );
|
||||
}
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
this._unbindFormResetHandler();
|
||||
|
||||
if ( this.icon ) {
|
||||
this.icon.remove();
|
||||
this.iconSpace.remove();
|
||||
}
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
|
||||
// We don't allow the value to be set to nothing
|
||||
if ( key === "label" && !value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this._toggleClass( this.label, null, "ui-state-disabled", value );
|
||||
this.element[ 0 ].disabled = value;
|
||||
|
||||
// Don't refresh when setting disabled
|
||||
return;
|
||||
}
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
_updateIcon: function( checked ) {
|
||||
var toAdd = "ui-icon ui-icon-background ";
|
||||
|
||||
if ( this.options.icon ) {
|
||||
if ( !this.icon ) {
|
||||
this.icon = $( "<span>" );
|
||||
this.iconSpace = $( "<span> </span>" );
|
||||
this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
|
||||
}
|
||||
|
||||
if ( this.type === "checkbox" ) {
|
||||
toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
|
||||
this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
|
||||
} else {
|
||||
toAdd += "ui-icon-blank";
|
||||
}
|
||||
this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
|
||||
if ( !checked ) {
|
||||
this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
|
||||
}
|
||||
this.icon.prependTo( this.label ).after( this.iconSpace );
|
||||
} else if ( this.icon !== undefined ) {
|
||||
this.icon.remove();
|
||||
this.iconSpace.remove();
|
||||
delete this.icon;
|
||||
}
|
||||
},
|
||||
|
||||
_updateLabel: function() {
|
||||
|
||||
// Remove the contents of the label ( minus the icon, icon space, and input )
|
||||
var contents = this.label.contents().not( this.element[ 0 ] );
|
||||
if ( this.icon ) {
|
||||
contents = contents.not( this.icon[ 0 ] );
|
||||
}
|
||||
if ( this.iconSpace ) {
|
||||
contents = contents.not( this.iconSpace[ 0 ] );
|
||||
}
|
||||
contents.remove();
|
||||
|
||||
this.label.append( this.options.label );
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
var checked = this.element[ 0 ].checked,
|
||||
isDisabled = this.element[ 0 ].disabled;
|
||||
|
||||
this._updateIcon( checked );
|
||||
this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
|
||||
if ( this.options.label !== null ) {
|
||||
this._updateLabel();
|
||||
}
|
||||
|
||||
if ( isDisabled !== this.options.disabled ) {
|
||||
this._setOptions( { "disabled": isDisabled } );
|
||||
}
|
||||
}
|
||||
|
||||
} ] );
|
||||
|
||||
return $.ui.checkboxradio;
|
||||
|
||||
} );
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* jQuery UI Checkboxradio 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./core"],e):e(jQuery)}(function(t){"use strict";return t.widget("ui.checkboxradio",[t.ui.formResetMixin,{version:"1.13.2",options:{disabled:null,label:null,icon:!0,classes:{"ui-checkboxradio-label":"ui-corner-all","ui-checkboxradio-icon":"ui-corner-all"}},_getCreateOptions:function(){var e,i=this._super()||{};return this._readType(),e=this.element.labels(),this.label=t(e[e.length-1]),this.label.length||t.error("No label found for checkboxradio widget"),this.originalLabel="",(e=this.label.contents().not(this.element[0])).length&&(this.originalLabel+=e.clone().wrapAll("<div></div>").parent().html()),this.originalLabel&&(i.label=this.originalLabel),null!=(e=this.element[0].disabled)&&(i.disabled=e),i},_create:function(){var e=this.element[0].checked;this._bindFormResetHandler(),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled),this._setOption("disabled",this.options.disabled),this._addClass("ui-checkboxradio","ui-helper-hidden-accessible"),this._addClass(this.label,"ui-checkboxradio-label","ui-button ui-widget"),"radio"===this.type&&this._addClass(this.label,"ui-checkboxradio-radio-label"),this.options.label&&this.options.label!==this.originalLabel?this._updateLabel():this.originalLabel&&(this.options.label=this.originalLabel),this._enhance(),e&&this._addClass(this.label,"ui-checkboxradio-checked","ui-state-active"),this._on({change:"_toggleClasses",focus:function(){this._addClass(this.label,null,"ui-state-focus ui-visual-focus")},blur:function(){this._removeClass(this.label,null,"ui-state-focus ui-visual-focus")}})},_readType:function(){var e=this.element[0].nodeName.toLowerCase();this.type=this.element[0].type,"input"===e&&/radio|checkbox/.test(this.type)||t.error("Can't create checkboxradio on element.nodeName="+e+" and element.type="+this.type)},_enhance:function(){this._updateIcon(this.element[0].checked)},widget:function(){return this.label},_getRadioGroup:function(){var e=this.element[0].name,i="input[name='"+t.escapeSelector(e)+"']";return e?(this.form.length?t(this.form[0].elements).filter(i):t(i).filter(function(){return 0===t(this)._form().length})).not(this.element):t([])},_toggleClasses:function(){var e=this.element[0].checked;this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",e),this.options.icon&&"checkbox"===this.type&&this._toggleClass(this.icon,null,"ui-icon-check ui-state-checked",e)._toggleClass(this.icon,null,"ui-icon-blank",!e),"radio"===this.type&&this._getRadioGroup().each(function(){var e=t(this).checkboxradio("instance");e&&e._removeClass(e.label,"ui-checkboxradio-checked","ui-state-active")})},_destroy:function(){this._unbindFormResetHandler(),this.icon&&(this.icon.remove(),this.iconSpace.remove())},_setOption:function(e,i){"label"===e&&!i||(this._super(e,i),"disabled"===e?(this._toggleClass(this.label,null,"ui-state-disabled",i),this.element[0].disabled=i):this.refresh())},_updateIcon:function(e){var i="ui-icon ui-icon-background ";this.options.icon?(this.icon||(this.icon=t("<span>"),this.iconSpace=t("<span> </span>"),this._addClass(this.iconSpace,"ui-checkboxradio-icon-space")),"checkbox"===this.type?(i+=e?"ui-icon-check ui-state-checked":"ui-icon-blank",this._removeClass(this.icon,null,e?"ui-icon-blank":"ui-icon-check")):i+="ui-icon-blank",this._addClass(this.icon,"ui-checkboxradio-icon",i),e||this._removeClass(this.icon,null,"ui-icon-check ui-state-checked"),this.icon.prependTo(this.label).after(this.iconSpace)):void 0!==this.icon&&(this.icon.remove(),this.iconSpace.remove(),delete this.icon)},_updateLabel:function(){var e=this.label.contents().not(this.element[0]);this.icon&&(e=e.not(this.icon[0])),(e=this.iconSpace?e.not(this.iconSpace[0]):e).remove(),this.label.append(this.options.label)},refresh:function(){var e=this.element[0].checked,i=this.element[0].disabled;this._updateIcon(e),this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",e),null!==this.options.label&&this._updateLabel(),i!==this.options.disabled&&this._setOptions({disabled:i})}}]),t.ui.checkboxradio});
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
/*!
|
||||
* jQuery UI Controlgroup 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Controlgroup
|
||||
//>>group: Widgets
|
||||
//>>description: Visually groups form control widgets
|
||||
//>>docs: http://api.jqueryui.com/controlgroup/
|
||||
//>>demos: http://jqueryui.com/controlgroup/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/controlgroup.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
|
||||
|
||||
$.widget( "ui.controlgroup", {
|
||||
version: "1.13.2",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
direction: "horizontal",
|
||||
disabled: null,
|
||||
onlyVisible: true,
|
||||
items: {
|
||||
"button": "input[type=button], input[type=submit], input[type=reset], button, a",
|
||||
"controlgroupLabel": ".ui-controlgroup-label",
|
||||
"checkboxradio": "input[type='checkbox'], input[type='radio']",
|
||||
"selectmenu": "select",
|
||||
"spinner": ".ui-spinner-input"
|
||||
}
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
this._enhance();
|
||||
},
|
||||
|
||||
// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
|
||||
_enhance: function() {
|
||||
this.element.attr( "role", "toolbar" );
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
this._callChildMethod( "destroy" );
|
||||
this.childWidgets.removeData( "ui-controlgroup-data" );
|
||||
this.element.removeAttr( "role" );
|
||||
if ( this.options.items.controlgroupLabel ) {
|
||||
this.element
|
||||
.find( this.options.items.controlgroupLabel )
|
||||
.find( ".ui-controlgroup-label-contents" )
|
||||
.contents().unwrap();
|
||||
}
|
||||
},
|
||||
|
||||
_initWidgets: function() {
|
||||
var that = this,
|
||||
childWidgets = [];
|
||||
|
||||
// First we iterate over each of the items options
|
||||
$.each( this.options.items, function( widget, selector ) {
|
||||
var labels;
|
||||
var options = {};
|
||||
|
||||
// Make sure the widget has a selector set
|
||||
if ( !selector ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( widget === "controlgroupLabel" ) {
|
||||
labels = that.element.find( selector );
|
||||
labels.each( function() {
|
||||
var element = $( this );
|
||||
|
||||
if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
|
||||
return;
|
||||
}
|
||||
element.contents()
|
||||
.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
|
||||
} );
|
||||
that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
|
||||
childWidgets = childWidgets.concat( labels.get() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the widget actually exists
|
||||
if ( !$.fn[ widget ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We assume everything is in the middle to start because we can't determine
|
||||
// first / last elements until all enhancments are done.
|
||||
if ( that[ "_" + widget + "Options" ] ) {
|
||||
options = that[ "_" + widget + "Options" ]( "middle" );
|
||||
} else {
|
||||
options = { classes: {} };
|
||||
}
|
||||
|
||||
// Find instances of this widget inside controlgroup and init them
|
||||
that.element
|
||||
.find( selector )
|
||||
.each( function() {
|
||||
var element = $( this );
|
||||
var instance = element[ widget ]( "instance" );
|
||||
|
||||
// We need to clone the default options for this type of widget to avoid
|
||||
// polluting the variable options which has a wider scope than a single widget.
|
||||
var instanceOptions = $.widget.extend( {}, options );
|
||||
|
||||
// If the button is the child of a spinner ignore it
|
||||
// TODO: Find a more generic solution
|
||||
if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the widget if it doesn't exist
|
||||
if ( !instance ) {
|
||||
instance = element[ widget ]()[ widget ]( "instance" );
|
||||
}
|
||||
if ( instance ) {
|
||||
instanceOptions.classes =
|
||||
that._resolveClassesValues( instanceOptions.classes, instance );
|
||||
}
|
||||
element[ widget ]( instanceOptions );
|
||||
|
||||
// Store an instance of the controlgroup to be able to reference
|
||||
// from the outermost element for changing options and refresh
|
||||
var widgetElement = element[ widget ]( "widget" );
|
||||
$.data( widgetElement[ 0 ], "ui-controlgroup-data",
|
||||
instance ? instance : element[ widget ]( "instance" ) );
|
||||
|
||||
childWidgets.push( widgetElement[ 0 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
this.childWidgets = $( $.uniqueSort( childWidgets ) );
|
||||
this._addClass( this.childWidgets, "ui-controlgroup-item" );
|
||||
},
|
||||
|
||||
_callChildMethod: function( method ) {
|
||||
this.childWidgets.each( function() {
|
||||
var element = $( this ),
|
||||
data = element.data( "ui-controlgroup-data" );
|
||||
if ( data && data[ method ] ) {
|
||||
data[ method ]();
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_updateCornerClass: function( element, position ) {
|
||||
var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
|
||||
var add = this._buildSimpleOptions( position, "label" ).classes.label;
|
||||
|
||||
this._removeClass( element, null, remove );
|
||||
this._addClass( element, null, add );
|
||||
},
|
||||
|
||||
_buildSimpleOptions: function( position, key ) {
|
||||
var direction = this.options.direction === "vertical";
|
||||
var result = {
|
||||
classes: {}
|
||||
};
|
||||
result.classes[ key ] = {
|
||||
"middle": "",
|
||||
"first": "ui-corner-" + ( direction ? "top" : "left" ),
|
||||
"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
|
||||
"only": "ui-corner-all"
|
||||
}[ position ];
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
_spinnerOptions: function( position ) {
|
||||
var options = this._buildSimpleOptions( position, "ui-spinner" );
|
||||
|
||||
options.classes[ "ui-spinner-up" ] = "";
|
||||
options.classes[ "ui-spinner-down" ] = "";
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
_buttonOptions: function( position ) {
|
||||
return this._buildSimpleOptions( position, "ui-button" );
|
||||
},
|
||||
|
||||
_checkboxradioOptions: function( position ) {
|
||||
return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
|
||||
},
|
||||
|
||||
_selectmenuOptions: function( position ) {
|
||||
var direction = this.options.direction === "vertical";
|
||||
return {
|
||||
width: direction ? "auto" : false,
|
||||
classes: {
|
||||
middle: {
|
||||
"ui-selectmenu-button-open": "",
|
||||
"ui-selectmenu-button-closed": ""
|
||||
},
|
||||
first: {
|
||||
"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
|
||||
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
|
||||
},
|
||||
last: {
|
||||
"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
|
||||
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
|
||||
},
|
||||
only: {
|
||||
"ui-selectmenu-button-open": "ui-corner-top",
|
||||
"ui-selectmenu-button-closed": "ui-corner-all"
|
||||
}
|
||||
|
||||
}[ position ]
|
||||
};
|
||||
},
|
||||
|
||||
_resolveClassesValues: function( classes, instance ) {
|
||||
var result = {};
|
||||
$.each( classes, function( key ) {
|
||||
var current = instance.options.classes[ key ] || "";
|
||||
current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
|
||||
result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
|
||||
} );
|
||||
return result;
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
if ( key === "direction" ) {
|
||||
this._removeClass( "ui-controlgroup-" + this.options.direction );
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
if ( key === "disabled" ) {
|
||||
this._callChildMethod( value ? "disable" : "enable" );
|
||||
return;
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
var children,
|
||||
that = this;
|
||||
|
||||
this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
|
||||
|
||||
if ( this.options.direction === "horizontal" ) {
|
||||
this._addClass( null, "ui-helper-clearfix" );
|
||||
}
|
||||
this._initWidgets();
|
||||
|
||||
children = this.childWidgets;
|
||||
|
||||
// We filter here because we need to track all childWidgets not just the visible ones
|
||||
if ( this.options.onlyVisible ) {
|
||||
children = children.filter( ":visible" );
|
||||
}
|
||||
|
||||
if ( children.length ) {
|
||||
|
||||
// We do this last because we need to make sure all enhancment is done
|
||||
// before determining first and last
|
||||
$.each( [ "first", "last" ], function( index, value ) {
|
||||
var instance = children[ value ]().data( "ui-controlgroup-data" );
|
||||
|
||||
if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
|
||||
var options = that[ "_" + instance.widgetName + "Options" ](
|
||||
children.length === 1 ? "only" : value
|
||||
);
|
||||
options.classes = that._resolveClassesValues( options.classes, instance );
|
||||
instance.element[ instance.widgetName ]( options );
|
||||
} else {
|
||||
that._updateCornerClass( children[ value ](), value );
|
||||
}
|
||||
} );
|
||||
|
||||
// Finally call the refresh method on each of the child widgets.
|
||||
this._callChildMethod( "refresh" );
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* jQuery UI Controlgroup 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery","./core"],t):t(jQuery)}(function(r){"use strict";var s=/ui-corner-([a-z]){2,6}/g;r.widget("ui.controlgroup",{version:"1.13.2",defaultElement:"<div>",options:{direction:"horizontal",disabled:null,onlyVisible:!0,items:{button:"input[type=button], input[type=submit], input[type=reset], button, a",controlgroupLabel:".ui-controlgroup-label",checkboxradio:"input[type='checkbox'], input[type='radio']",selectmenu:"select",spinner:".ui-spinner-input"}},_create:function(){this._enhance()},_enhance:function(){this.element.attr("role","toolbar"),this.refresh()},_destroy:function(){this._callChildMethod("destroy"),this.childWidgets.removeData("ui-controlgroup-data"),this.element.removeAttr("role"),this.options.items.controlgroupLabel&&this.element.find(this.options.items.controlgroupLabel).find(".ui-controlgroup-label-contents").contents().unwrap()},_initWidgets:function(){var s=this,l=[];r.each(this.options.items,function(n,t){var e,o={};t&&("controlgroupLabel"===n?((e=s.element.find(t)).each(function(){var t=r(this);t.children(".ui-controlgroup-label-contents").length||t.contents().wrapAll("<span class='ui-controlgroup-label-contents'></span>")}),s._addClass(e,null,"ui-widget ui-widget-content ui-state-default"),l=l.concat(e.get())):r.fn[n]&&(o=s["_"+n+"Options"]?s["_"+n+"Options"]("middle"):{classes:{}},s.element.find(t).each(function(){var t=r(this),e=t[n]("instance"),i=r.widget.extend({},o);"button"===n&&t.parent(".ui-spinner").length||((e=e||t[n]()[n]("instance"))&&(i.classes=s._resolveClassesValues(i.classes,e)),t[n](i),i=t[n]("widget"),r.data(i[0],"ui-controlgroup-data",e||t[n]("instance")),l.push(i[0]))})))}),this.childWidgets=r(r.uniqueSort(l)),this._addClass(this.childWidgets,"ui-controlgroup-item")},_callChildMethod:function(e){this.childWidgets.each(function(){var t=r(this).data("ui-controlgroup-data");t&&t[e]&&t[e]()})},_updateCornerClass:function(t,e){e=this._buildSimpleOptions(e,"label").classes.label;this._removeClass(t,null,"ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"),this._addClass(t,null,e)},_buildSimpleOptions:function(t,e){var i="vertical"===this.options.direction,n={classes:{}};return n.classes[e]={middle:"",first:"ui-corner-"+(i?"top":"left"),last:"ui-corner-"+(i?"bottom":"right"),only:"ui-corner-all"}[t],n},_spinnerOptions:function(t){t=this._buildSimpleOptions(t,"ui-spinner");return t.classes["ui-spinner-up"]="",t.classes["ui-spinner-down"]="",t},_buttonOptions:function(t){return this._buildSimpleOptions(t,"ui-button")},_checkboxradioOptions:function(t){return this._buildSimpleOptions(t,"ui-checkboxradio-label")},_selectmenuOptions:function(t){var e="vertical"===this.options.direction;return{width:e&&"auto",classes:{middle:{"ui-selectmenu-button-open":"","ui-selectmenu-button-closed":""},first:{"ui-selectmenu-button-open":"ui-corner-"+(e?"top":"tl"),"ui-selectmenu-button-closed":"ui-corner-"+(e?"top":"left")},last:{"ui-selectmenu-button-open":e?"":"ui-corner-tr","ui-selectmenu-button-closed":"ui-corner-"+(e?"bottom":"right")},only:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"}}[t]}},_resolveClassesValues:function(i,n){var o={};return r.each(i,function(t){var e=n.options.classes[t]||"",e=String.prototype.trim.call(e.replace(s,""));o[t]=(e+" "+i[t]).replace(/\s+/g," ")}),o},_setOption:function(t,e){"direction"===t&&this._removeClass("ui-controlgroup-"+this.options.direction),this._super(t,e),"disabled"===t?this._callChildMethod(e?"disable":"enable"):this.refresh()},refresh:function(){var o,s=this;this._addClass("ui-controlgroup ui-controlgroup-"+this.options.direction),"horizontal"===this.options.direction&&this._addClass(null,"ui-helper-clearfix"),this._initWidgets(),o=this.childWidgets,(o=this.options.onlyVisible?o.filter(":visible"):o).length&&(r.each(["first","last"],function(t,e){var i,n=o[e]().data("ui-controlgroup-data");n&&s["_"+n.widgetName+"Options"]?((i=s["_"+n.widgetName+"Options"](1===o.length?"only":e)).classes=s._resolveClassesValues(i.classes,n),n.element[n.widgetName](i)):s._updateCornerClass(o[e](),e)}),this._callChildMethod("refresh"))}})});
|
||||
+1790
File diff suppressed because it is too large
Load Diff
+116
File diff suppressed because one or more lines are too long
+2239
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+946
@@ -0,0 +1,946 @@
|
||||
/*!
|
||||
* jQuery UI Dialog 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Dialog
|
||||
//>>group: Widgets
|
||||
//>>description: Displays customizable dialog windows.
|
||||
//>>docs: http://api.jqueryui.com/dialog/
|
||||
//>>demos: http://jqueryui.com/dialog/
|
||||
//>>css.structure: ../../themes/base/core.css
|
||||
//>>css.structure: ../../themes/base/dialog.css
|
||||
//>>css.theme: ../../themes/base/theme.css
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./button",
|
||||
"./draggable",
|
||||
"./mouse",
|
||||
"./resizable",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.widget( "ui.dialog", {
|
||||
version: "1.13.2",
|
||||
options: {
|
||||
appendTo: "body",
|
||||
autoOpen: true,
|
||||
buttons: [],
|
||||
classes: {
|
||||
"ui-dialog": "ui-corner-all",
|
||||
"ui-dialog-titlebar": "ui-corner-all"
|
||||
},
|
||||
closeOnEscape: true,
|
||||
closeText: "Close",
|
||||
draggable: true,
|
||||
hide: null,
|
||||
height: "auto",
|
||||
maxHeight: null,
|
||||
maxWidth: null,
|
||||
minHeight: 150,
|
||||
minWidth: 150,
|
||||
modal: false,
|
||||
position: {
|
||||
my: "center",
|
||||
at: "center",
|
||||
of: window,
|
||||
collision: "fit",
|
||||
|
||||
// Ensure the titlebar is always visible
|
||||
using: function( pos ) {
|
||||
var topOffset = $( this ).css( pos ).offset().top;
|
||||
if ( topOffset < 0 ) {
|
||||
$( this ).css( "top", pos.top - topOffset );
|
||||
}
|
||||
}
|
||||
},
|
||||
resizable: true,
|
||||
show: null,
|
||||
title: null,
|
||||
width: 300,
|
||||
|
||||
// Callbacks
|
||||
beforeClose: null,
|
||||
close: null,
|
||||
drag: null,
|
||||
dragStart: null,
|
||||
dragStop: null,
|
||||
focus: null,
|
||||
open: null,
|
||||
resize: null,
|
||||
resizeStart: null,
|
||||
resizeStop: null
|
||||
},
|
||||
|
||||
sizeRelatedOptions: {
|
||||
buttons: true,
|
||||
height: true,
|
||||
maxHeight: true,
|
||||
maxWidth: true,
|
||||
minHeight: true,
|
||||
minWidth: true,
|
||||
width: true
|
||||
},
|
||||
|
||||
resizableRelatedOptions: {
|
||||
maxHeight: true,
|
||||
maxWidth: true,
|
||||
minHeight: true,
|
||||
minWidth: true
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
this.originalCss = {
|
||||
display: this.element[ 0 ].style.display,
|
||||
width: this.element[ 0 ].style.width,
|
||||
minHeight: this.element[ 0 ].style.minHeight,
|
||||
maxHeight: this.element[ 0 ].style.maxHeight,
|
||||
height: this.element[ 0 ].style.height
|
||||
};
|
||||
this.originalPosition = {
|
||||
parent: this.element.parent(),
|
||||
index: this.element.parent().children().index( this.element )
|
||||
};
|
||||
this.originalTitle = this.element.attr( "title" );
|
||||
if ( this.options.title == null && this.originalTitle != null ) {
|
||||
this.options.title = this.originalTitle;
|
||||
}
|
||||
|
||||
// Dialogs can't be disabled
|
||||
if ( this.options.disabled ) {
|
||||
this.options.disabled = false;
|
||||
}
|
||||
|
||||
this._createWrapper();
|
||||
|
||||
this.element
|
||||
.show()
|
||||
.removeAttr( "title" )
|
||||
.appendTo( this.uiDialog );
|
||||
|
||||
this._addClass( "ui-dialog-content", "ui-widget-content" );
|
||||
|
||||
this._createTitlebar();
|
||||
this._createButtonPane();
|
||||
|
||||
if ( this.options.draggable && $.fn.draggable ) {
|
||||
this._makeDraggable();
|
||||
}
|
||||
if ( this.options.resizable && $.fn.resizable ) {
|
||||
this._makeResizable();
|
||||
}
|
||||
|
||||
this._isOpen = false;
|
||||
|
||||
this._trackFocus();
|
||||
},
|
||||
|
||||
_init: function() {
|
||||
if ( this.options.autoOpen ) {
|
||||
this.open();
|
||||
}
|
||||
},
|
||||
|
||||
_appendTo: function() {
|
||||
var element = this.options.appendTo;
|
||||
if ( element && ( element.jquery || element.nodeType ) ) {
|
||||
return $( element );
|
||||
}
|
||||
return this.document.find( element || "body" ).eq( 0 );
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
var next,
|
||||
originalPosition = this.originalPosition;
|
||||
|
||||
this._untrackInstance();
|
||||
this._destroyOverlay();
|
||||
|
||||
this.element
|
||||
.removeUniqueId()
|
||||
.css( this.originalCss )
|
||||
|
||||
// Without detaching first, the following becomes really slow
|
||||
.detach();
|
||||
|
||||
this.uiDialog.remove();
|
||||
|
||||
if ( this.originalTitle ) {
|
||||
this.element.attr( "title", this.originalTitle );
|
||||
}
|
||||
|
||||
next = originalPosition.parent.children().eq( originalPosition.index );
|
||||
|
||||
// Don't try to place the dialog next to itself (#8613)
|
||||
if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
|
||||
next.before( this.element );
|
||||
} else {
|
||||
originalPosition.parent.append( this.element );
|
||||
}
|
||||
},
|
||||
|
||||
widget: function() {
|
||||
return this.uiDialog;
|
||||
},
|
||||
|
||||
disable: $.noop,
|
||||
enable: $.noop,
|
||||
|
||||
close: function( event ) {
|
||||
var that = this;
|
||||
|
||||
if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isOpen = false;
|
||||
this._focusedElement = null;
|
||||
this._destroyOverlay();
|
||||
this._untrackInstance();
|
||||
|
||||
if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
|
||||
|
||||
// Hiding a focused element doesn't trigger blur in WebKit
|
||||
// so in case we have nothing to focus on, explicitly blur the active element
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=47182
|
||||
$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
|
||||
}
|
||||
|
||||
this._hide( this.uiDialog, this.options.hide, function() {
|
||||
that._trigger( "close", event );
|
||||
} );
|
||||
},
|
||||
|
||||
isOpen: function() {
|
||||
return this._isOpen;
|
||||
},
|
||||
|
||||
moveToTop: function() {
|
||||
this._moveToTop();
|
||||
},
|
||||
|
||||
_moveToTop: function( event, silent ) {
|
||||
var moved = false,
|
||||
zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
|
||||
return +$( this ).css( "z-index" );
|
||||
} ).get(),
|
||||
zIndexMax = Math.max.apply( null, zIndices );
|
||||
|
||||
if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
|
||||
this.uiDialog.css( "z-index", zIndexMax + 1 );
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if ( moved && !silent ) {
|
||||
this._trigger( "focus", event );
|
||||
}
|
||||
return moved;
|
||||
},
|
||||
|
||||
open: function() {
|
||||
var that = this;
|
||||
if ( this._isOpen ) {
|
||||
if ( this._moveToTop() ) {
|
||||
this._focusTabbable();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._isOpen = true;
|
||||
this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
|
||||
|
||||
this._size();
|
||||
this._position();
|
||||
this._createOverlay();
|
||||
this._moveToTop( null, true );
|
||||
|
||||
// Ensure the overlay is moved to the top with the dialog, but only when
|
||||
// opening. The overlay shouldn't move after the dialog is open so that
|
||||
// modeless dialogs opened after the modal dialog stack properly.
|
||||
if ( this.overlay ) {
|
||||
this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
|
||||
}
|
||||
|
||||
this._show( this.uiDialog, this.options.show, function() {
|
||||
that._focusTabbable();
|
||||
that._trigger( "focus" );
|
||||
} );
|
||||
|
||||
// Track the dialog immediately upon opening in case a focus event
|
||||
// somehow occurs outside of the dialog before an element inside the
|
||||
// dialog is focused (#10152)
|
||||
this._makeFocusTarget();
|
||||
|
||||
this._trigger( "open" );
|
||||
},
|
||||
|
||||
_focusTabbable: function() {
|
||||
|
||||
// Set focus to the first match:
|
||||
// 1. An element that was focused previously
|
||||
// 2. First element inside the dialog matching [autofocus]
|
||||
// 3. Tabbable element inside the content element
|
||||
// 4. Tabbable element inside the buttonpane
|
||||
// 5. The close button
|
||||
// 6. The dialog itself
|
||||
var hasFocus = this._focusedElement;
|
||||
if ( !hasFocus ) {
|
||||
hasFocus = this.element.find( "[autofocus]" );
|
||||
}
|
||||
if ( !hasFocus.length ) {
|
||||
hasFocus = this.element.find( ":tabbable" );
|
||||
}
|
||||
if ( !hasFocus.length ) {
|
||||
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
|
||||
}
|
||||
if ( !hasFocus.length ) {
|
||||
hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
|
||||
}
|
||||
if ( !hasFocus.length ) {
|
||||
hasFocus = this.uiDialog;
|
||||
}
|
||||
hasFocus.eq( 0 ).trigger( "focus" );
|
||||
},
|
||||
|
||||
_restoreTabbableFocus: function() {
|
||||
var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
|
||||
isActive = this.uiDialog[ 0 ] === activeElement ||
|
||||
$.contains( this.uiDialog[ 0 ], activeElement );
|
||||
if ( !isActive ) {
|
||||
this._focusTabbable();
|
||||
}
|
||||
},
|
||||
|
||||
_keepFocus: function( event ) {
|
||||
event.preventDefault();
|
||||
this._restoreTabbableFocus();
|
||||
|
||||
// support: IE
|
||||
// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
|
||||
// so we check again later
|
||||
this._delay( this._restoreTabbableFocus );
|
||||
},
|
||||
|
||||
_createWrapper: function() {
|
||||
this.uiDialog = $( "<div>" )
|
||||
.hide()
|
||||
.attr( {
|
||||
|
||||
// Setting tabIndex makes the div focusable
|
||||
tabIndex: -1,
|
||||
role: "dialog"
|
||||
} )
|
||||
.appendTo( this._appendTo() );
|
||||
|
||||
this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
|
||||
this._on( this.uiDialog, {
|
||||
keydown: function( event ) {
|
||||
if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
|
||||
event.keyCode === $.ui.keyCode.ESCAPE ) {
|
||||
event.preventDefault();
|
||||
this.close( event );
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent tabbing out of dialogs
|
||||
if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
|
||||
return;
|
||||
}
|
||||
var tabbables = this.uiDialog.find( ":tabbable" ),
|
||||
first = tabbables.first(),
|
||||
last = tabbables.last();
|
||||
|
||||
if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
|
||||
!event.shiftKey ) {
|
||||
this._delay( function() {
|
||||
first.trigger( "focus" );
|
||||
} );
|
||||
event.preventDefault();
|
||||
} else if ( ( event.target === first[ 0 ] ||
|
||||
event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
|
||||
this._delay( function() {
|
||||
last.trigger( "focus" );
|
||||
} );
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
mousedown: function( event ) {
|
||||
if ( this._moveToTop( event ) ) {
|
||||
this._focusTabbable();
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// We assume that any existing aria-describedby attribute means
|
||||
// that the dialog content is marked up properly
|
||||
// otherwise we brute force the content as the description
|
||||
if ( !this.element.find( "[aria-describedby]" ).length ) {
|
||||
this.uiDialog.attr( {
|
||||
"aria-describedby": this.element.uniqueId().attr( "id" )
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
_createTitlebar: function() {
|
||||
var uiDialogTitle;
|
||||
|
||||
this.uiDialogTitlebar = $( "<div>" );
|
||||
this._addClass( this.uiDialogTitlebar,
|
||||
"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
|
||||
this._on( this.uiDialogTitlebar, {
|
||||
mousedown: function( event ) {
|
||||
|
||||
// Don't prevent click on close button (#8838)
|
||||
// Focusing a dialog that is partially scrolled out of view
|
||||
// causes the browser to scroll it into view, preventing the click event
|
||||
if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
|
||||
|
||||
// Dialog isn't getting focus when dragging (#8063)
|
||||
this.uiDialog.trigger( "focus" );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Support: IE
|
||||
// Use type="button" to prevent enter keypresses in textboxes from closing the
|
||||
// dialog in IE (#9312)
|
||||
this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
|
||||
.button( {
|
||||
label: $( "<a>" ).text( this.options.closeText ).html(),
|
||||
icon: "ui-icon-closethick",
|
||||
showLabel: false
|
||||
} )
|
||||
.appendTo( this.uiDialogTitlebar );
|
||||
|
||||
this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
|
||||
this._on( this.uiDialogTitlebarClose, {
|
||||
click: function( event ) {
|
||||
event.preventDefault();
|
||||
this.close( event );
|
||||
}
|
||||
} );
|
||||
|
||||
uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
|
||||
this._addClass( uiDialogTitle, "ui-dialog-title" );
|
||||
this._title( uiDialogTitle );
|
||||
|
||||
this.uiDialogTitlebar.prependTo( this.uiDialog );
|
||||
|
||||
this.uiDialog.attr( {
|
||||
"aria-labelledby": uiDialogTitle.attr( "id" )
|
||||
} );
|
||||
},
|
||||
|
||||
_title: function( title ) {
|
||||
if ( this.options.title ) {
|
||||
title.text( this.options.title );
|
||||
} else {
|
||||
title.html( " " );
|
||||
}
|
||||
},
|
||||
|
||||
_createButtonPane: function() {
|
||||
this.uiDialogButtonPane = $( "<div>" );
|
||||
this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
|
||||
"ui-widget-content ui-helper-clearfix" );
|
||||
|
||||
this.uiButtonSet = $( "<div>" )
|
||||
.appendTo( this.uiDialogButtonPane );
|
||||
this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
|
||||
|
||||
this._createButtons();
|
||||
},
|
||||
|
||||
_createButtons: function() {
|
||||
var that = this,
|
||||
buttons = this.options.buttons;
|
||||
|
||||
// If we already have a button pane, remove it
|
||||
this.uiDialogButtonPane.remove();
|
||||
this.uiButtonSet.empty();
|
||||
|
||||
if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
|
||||
this._removeClass( this.uiDialog, "ui-dialog-buttons" );
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( buttons, function( name, props ) {
|
||||
var click, buttonOptions;
|
||||
props = typeof props === "function" ?
|
||||
{ click: props, text: name } :
|
||||
props;
|
||||
|
||||
// Default to a non-submitting button
|
||||
props = $.extend( { type: "button" }, props );
|
||||
|
||||
// Change the context for the click callback to be the main element
|
||||
click = props.click;
|
||||
buttonOptions = {
|
||||
icon: props.icon,
|
||||
iconPosition: props.iconPosition,
|
||||
showLabel: props.showLabel,
|
||||
|
||||
// Deprecated options
|
||||
icons: props.icons,
|
||||
text: props.text
|
||||
};
|
||||
|
||||
delete props.click;
|
||||
delete props.icon;
|
||||
delete props.iconPosition;
|
||||
delete props.showLabel;
|
||||
|
||||
// Deprecated options
|
||||
delete props.icons;
|
||||
if ( typeof props.text === "boolean" ) {
|
||||
delete props.text;
|
||||
}
|
||||
|
||||
$( "<button></button>", props )
|
||||
.button( buttonOptions )
|
||||
.appendTo( that.uiButtonSet )
|
||||
.on( "click", function() {
|
||||
click.apply( that.element[ 0 ], arguments );
|
||||
} );
|
||||
} );
|
||||
this._addClass( this.uiDialog, "ui-dialog-buttons" );
|
||||
this.uiDialogButtonPane.appendTo( this.uiDialog );
|
||||
},
|
||||
|
||||
_makeDraggable: function() {
|
||||
var that = this,
|
||||
options = this.options;
|
||||
|
||||
function filteredUi( ui ) {
|
||||
return {
|
||||
position: ui.position,
|
||||
offset: ui.offset
|
||||
};
|
||||
}
|
||||
|
||||
this.uiDialog.draggable( {
|
||||
cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
|
||||
handle: ".ui-dialog-titlebar",
|
||||
containment: "document",
|
||||
start: function( event, ui ) {
|
||||
that._addClass( $( this ), "ui-dialog-dragging" );
|
||||
that._blockFrames();
|
||||
that._trigger( "dragStart", event, filteredUi( ui ) );
|
||||
},
|
||||
drag: function( event, ui ) {
|
||||
that._trigger( "drag", event, filteredUi( ui ) );
|
||||
},
|
||||
stop: function( event, ui ) {
|
||||
var left = ui.offset.left - that.document.scrollLeft(),
|
||||
top = ui.offset.top - that.document.scrollTop();
|
||||
|
||||
options.position = {
|
||||
my: "left top",
|
||||
at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
|
||||
"top" + ( top >= 0 ? "+" : "" ) + top,
|
||||
of: that.window
|
||||
};
|
||||
that._removeClass( $( this ), "ui-dialog-dragging" );
|
||||
that._unblockFrames();
|
||||
that._trigger( "dragStop", event, filteredUi( ui ) );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_makeResizable: function() {
|
||||
var that = this,
|
||||
options = this.options,
|
||||
handles = options.resizable,
|
||||
|
||||
// .ui-resizable has position: relative defined in the stylesheet
|
||||
// but dialogs have to use absolute or fixed positioning
|
||||
position = this.uiDialog.css( "position" ),
|
||||
resizeHandles = typeof handles === "string" ?
|
||||
handles :
|
||||
"n,e,s,w,se,sw,ne,nw";
|
||||
|
||||
function filteredUi( ui ) {
|
||||
return {
|
||||
originalPosition: ui.originalPosition,
|
||||
originalSize: ui.originalSize,
|
||||
position: ui.position,
|
||||
size: ui.size
|
||||
};
|
||||
}
|
||||
|
||||
this.uiDialog.resizable( {
|
||||
cancel: ".ui-dialog-content",
|
||||
containment: "document",
|
||||
alsoResize: this.element,
|
||||
maxWidth: options.maxWidth,
|
||||
maxHeight: options.maxHeight,
|
||||
minWidth: options.minWidth,
|
||||
minHeight: this._minHeight(),
|
||||
handles: resizeHandles,
|
||||
start: function( event, ui ) {
|
||||
that._addClass( $( this ), "ui-dialog-resizing" );
|
||||
that._blockFrames();
|
||||
that._trigger( "resizeStart", event, filteredUi( ui ) );
|
||||
},
|
||||
resize: function( event, ui ) {
|
||||
that._trigger( "resize", event, filteredUi( ui ) );
|
||||
},
|
||||
stop: function( event, ui ) {
|
||||
var offset = that.uiDialog.offset(),
|
||||
left = offset.left - that.document.scrollLeft(),
|
||||
top = offset.top - that.document.scrollTop();
|
||||
|
||||
options.height = that.uiDialog.height();
|
||||
options.width = that.uiDialog.width();
|
||||
options.position = {
|
||||
my: "left top",
|
||||
at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
|
||||
"top" + ( top >= 0 ? "+" : "" ) + top,
|
||||
of: that.window
|
||||
};
|
||||
that._removeClass( $( this ), "ui-dialog-resizing" );
|
||||
that._unblockFrames();
|
||||
that._trigger( "resizeStop", event, filteredUi( ui ) );
|
||||
}
|
||||
} )
|
||||
.css( "position", position );
|
||||
},
|
||||
|
||||
_trackFocus: function() {
|
||||
this._on( this.widget(), {
|
||||
focusin: function( event ) {
|
||||
this._makeFocusTarget();
|
||||
this._focusedElement = $( event.target );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
_makeFocusTarget: function() {
|
||||
this._untrackInstance();
|
||||
this._trackingInstances().unshift( this );
|
||||
},
|
||||
|
||||
_untrackInstance: function() {
|
||||
var instances = this._trackingInstances(),
|
||||
exists = $.inArray( this, instances );
|
||||
if ( exists !== -1 ) {
|
||||
instances.splice( exists, 1 );
|
||||
}
|
||||
},
|
||||
|
||||
_trackingInstances: function() {
|
||||
var instances = this.document.data( "ui-dialog-instances" );
|
||||
if ( !instances ) {
|
||||
instances = [];
|
||||
this.document.data( "ui-dialog-instances", instances );
|
||||
}
|
||||
return instances;
|
||||
},
|
||||
|
||||
_minHeight: function() {
|
||||
var options = this.options;
|
||||
|
||||
return options.height === "auto" ?
|
||||
options.minHeight :
|
||||
Math.min( options.minHeight, options.height );
|
||||
},
|
||||
|
||||
_position: function() {
|
||||
|
||||
// Need to show the dialog to get the actual offset in the position plugin
|
||||
var isVisible = this.uiDialog.is( ":visible" );
|
||||
if ( !isVisible ) {
|
||||
this.uiDialog.show();
|
||||
}
|
||||
this.uiDialog.position( this.options.position );
|
||||
if ( !isVisible ) {
|
||||
this.uiDialog.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_setOptions: function( options ) {
|
||||
var that = this,
|
||||
resize = false,
|
||||
resizableOptions = {};
|
||||
|
||||
$.each( options, function( key, value ) {
|
||||
that._setOption( key, value );
|
||||
|
||||
if ( key in that.sizeRelatedOptions ) {
|
||||
resize = true;
|
||||
}
|
||||
if ( key in that.resizableRelatedOptions ) {
|
||||
resizableOptions[ key ] = value;
|
||||
}
|
||||
} );
|
||||
|
||||
if ( resize ) {
|
||||
this._size();
|
||||
this._position();
|
||||
}
|
||||
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
|
||||
this.uiDialog.resizable( "option", resizableOptions );
|
||||
}
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
var isDraggable, isResizable,
|
||||
uiDialog = this.uiDialog;
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
|
||||
if ( key === "appendTo" ) {
|
||||
this.uiDialog.appendTo( this._appendTo() );
|
||||
}
|
||||
|
||||
if ( key === "buttons" ) {
|
||||
this._createButtons();
|
||||
}
|
||||
|
||||
if ( key === "closeText" ) {
|
||||
this.uiDialogTitlebarClose.button( {
|
||||
|
||||
// Ensure that we always pass a string
|
||||
label: $( "<a>" ).text( "" + this.options.closeText ).html()
|
||||
} );
|
||||
}
|
||||
|
||||
if ( key === "draggable" ) {
|
||||
isDraggable = uiDialog.is( ":data(ui-draggable)" );
|
||||
if ( isDraggable && !value ) {
|
||||
uiDialog.draggable( "destroy" );
|
||||
}
|
||||
|
||||
if ( !isDraggable && value ) {
|
||||
this._makeDraggable();
|
||||
}
|
||||
}
|
||||
|
||||
if ( key === "position" ) {
|
||||
this._position();
|
||||
}
|
||||
|
||||
if ( key === "resizable" ) {
|
||||
|
||||
// currently resizable, becoming non-resizable
|
||||
isResizable = uiDialog.is( ":data(ui-resizable)" );
|
||||
if ( isResizable && !value ) {
|
||||
uiDialog.resizable( "destroy" );
|
||||
}
|
||||
|
||||
// Currently resizable, changing handles
|
||||
if ( isResizable && typeof value === "string" ) {
|
||||
uiDialog.resizable( "option", "handles", value );
|
||||
}
|
||||
|
||||
// Currently non-resizable, becoming resizable
|
||||
if ( !isResizable && value !== false ) {
|
||||
this._makeResizable();
|
||||
}
|
||||
}
|
||||
|
||||
if ( key === "title" ) {
|
||||
this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
|
||||
}
|
||||
},
|
||||
|
||||
_size: function() {
|
||||
|
||||
// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
|
||||
// divs will both have width and height set, so we need to reset them
|
||||
var nonContentHeight, minContentHeight, maxContentHeight,
|
||||
options = this.options;
|
||||
|
||||
// Reset content sizing
|
||||
this.element.show().css( {
|
||||
width: "auto",
|
||||
minHeight: 0,
|
||||
maxHeight: "none",
|
||||
height: 0
|
||||
} );
|
||||
|
||||
if ( options.minWidth > options.width ) {
|
||||
options.width = options.minWidth;
|
||||
}
|
||||
|
||||
// Reset wrapper sizing
|
||||
// determine the height of all the non-content elements
|
||||
nonContentHeight = this.uiDialog.css( {
|
||||
height: "auto",
|
||||
width: options.width
|
||||
} )
|
||||
.outerHeight();
|
||||
minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
|
||||
maxContentHeight = typeof options.maxHeight === "number" ?
|
||||
Math.max( 0, options.maxHeight - nonContentHeight ) :
|
||||
"none";
|
||||
|
||||
if ( options.height === "auto" ) {
|
||||
this.element.css( {
|
||||
minHeight: minContentHeight,
|
||||
maxHeight: maxContentHeight,
|
||||
height: "auto"
|
||||
} );
|
||||
} else {
|
||||
this.element.height( Math.max( 0, options.height - nonContentHeight ) );
|
||||
}
|
||||
|
||||
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
|
||||
this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
|
||||
}
|
||||
},
|
||||
|
||||
_blockFrames: function() {
|
||||
this.iframeBlocks = this.document.find( "iframe" ).map( function() {
|
||||
var iframe = $( this );
|
||||
|
||||
return $( "<div>" )
|
||||
.css( {
|
||||
position: "absolute",
|
||||
width: iframe.outerWidth(),
|
||||
height: iframe.outerHeight()
|
||||
} )
|
||||
.appendTo( iframe.parent() )
|
||||
.offset( iframe.offset() )[ 0 ];
|
||||
} );
|
||||
},
|
||||
|
||||
_unblockFrames: function() {
|
||||
if ( this.iframeBlocks ) {
|
||||
this.iframeBlocks.remove();
|
||||
delete this.iframeBlocks;
|
||||
}
|
||||
},
|
||||
|
||||
_allowInteraction: function( event ) {
|
||||
if ( $( event.target ).closest( ".ui-dialog" ).length ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Remove hack when datepicker implements
|
||||
// the .ui-front logic (#8989)
|
||||
return !!$( event.target ).closest( ".ui-datepicker" ).length;
|
||||
},
|
||||
|
||||
_createOverlay: function() {
|
||||
if ( !this.options.modal ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var jqMinor = $.fn.jquery.substring( 0, 4 );
|
||||
|
||||
// We use a delay in case the overlay is created from an
|
||||
// event that we're going to be cancelling (#2804)
|
||||
var isOpening = true;
|
||||
this._delay( function() {
|
||||
isOpening = false;
|
||||
} );
|
||||
|
||||
if ( !this.document.data( "ui-dialog-overlays" ) ) {
|
||||
|
||||
// Prevent use of anchors and inputs
|
||||
// This doesn't use `_on()` because it is a shared event handler
|
||||
// across all open modal dialogs.
|
||||
this.document.on( "focusin.ui-dialog", function( event ) {
|
||||
if ( isOpening ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var instance = this._trackingInstances()[ 0 ];
|
||||
if ( !instance._allowInteraction( event ) ) {
|
||||
event.preventDefault();
|
||||
instance._focusTabbable();
|
||||
|
||||
// Support: jQuery >=3.4 <3.6 only
|
||||
// Focus re-triggering in jQuery 3.4/3.5 makes the original element
|
||||
// have its focus event propagated last, breaking the re-targeting.
|
||||
// Trigger focus in a delay in addition if needed to avoid the issue
|
||||
// See https://github.com/jquery/jquery/issues/4382
|
||||
if ( jqMinor === "3.4." || jqMinor === "3.5." ) {
|
||||
instance._delay( instance._restoreTabbableFocus );
|
||||
}
|
||||
}
|
||||
}.bind( this ) );
|
||||
}
|
||||
|
||||
this.overlay = $( "<div>" )
|
||||
.appendTo( this._appendTo() );
|
||||
|
||||
this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
|
||||
this._on( this.overlay, {
|
||||
mousedown: "_keepFocus"
|
||||
} );
|
||||
this.document.data( "ui-dialog-overlays",
|
||||
( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
|
||||
},
|
||||
|
||||
_destroyOverlay: function() {
|
||||
if ( !this.options.modal ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.overlay ) {
|
||||
var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
|
||||
|
||||
if ( !overlays ) {
|
||||
this.document.off( "focusin.ui-dialog" );
|
||||
this.document.removeData( "ui-dialog-overlays" );
|
||||
} else {
|
||||
this.document.data( "ui-dialog-overlays", overlays );
|
||||
}
|
||||
|
||||
this.overlay.remove();
|
||||
this.overlay = null;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// DEPRECATED
|
||||
// TODO: switch return back to widget declaration at top of file when this is removed
|
||||
if ( $.uiBackCompat !== false ) {
|
||||
|
||||
// Backcompat for dialogClass option
|
||||
$.widget( "ui.dialog", $.ui.dialog, {
|
||||
options: {
|
||||
dialogClass: ""
|
||||
},
|
||||
_createWrapper: function() {
|
||||
this._super();
|
||||
this.uiDialog.addClass( this.options.dialogClass );
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
if ( key === "dialogClass" ) {
|
||||
this.uiDialog
|
||||
.removeClass( this.options.dialogClass )
|
||||
.addClass( value );
|
||||
}
|
||||
this._superApply( arguments );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return $.ui.dialog;
|
||||
|
||||
} );
|
||||
File diff suppressed because one or more lines are too long
+1253
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+502
@@ -0,0 +1,502 @@
|
||||
/*!
|
||||
* jQuery UI Droppable 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Droppable
|
||||
//>>group: Interactions
|
||||
//>>description: Enables drop targets for draggable elements.
|
||||
//>>docs: http://api.jqueryui.com/droppable/
|
||||
//>>demos: http://jqueryui.com/droppable/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./draggable",
|
||||
"./mouse",
|
||||
"./core"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.widget( "ui.droppable", {
|
||||
version: "1.13.2",
|
||||
widgetEventPrefix: "drop",
|
||||
options: {
|
||||
accept: "*",
|
||||
addClasses: true,
|
||||
greedy: false,
|
||||
scope: "default",
|
||||
tolerance: "intersect",
|
||||
|
||||
// Callbacks
|
||||
activate: null,
|
||||
deactivate: null,
|
||||
drop: null,
|
||||
out: null,
|
||||
over: null
|
||||
},
|
||||
_create: function() {
|
||||
|
||||
var proportions,
|
||||
o = this.options,
|
||||
accept = o.accept;
|
||||
|
||||
this.isover = false;
|
||||
this.isout = true;
|
||||
|
||||
this.accept = typeof accept === "function" ? accept : function( d ) {
|
||||
return d.is( accept );
|
||||
};
|
||||
|
||||
this.proportions = function( /* valueToWrite */ ) {
|
||||
if ( arguments.length ) {
|
||||
|
||||
// Store the droppable's proportions
|
||||
proportions = arguments[ 0 ];
|
||||
} else {
|
||||
|
||||
// Retrieve or derive the droppable's proportions
|
||||
return proportions ?
|
||||
proportions :
|
||||
proportions = {
|
||||
width: this.element[ 0 ].offsetWidth,
|
||||
height: this.element[ 0 ].offsetHeight
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
this._addToManager( o.scope );
|
||||
|
||||
if ( o.addClasses ) {
|
||||
this._addClass( "ui-droppable" );
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_addToManager: function( scope ) {
|
||||
|
||||
// Add the reference and positions to the manager
|
||||
$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
|
||||
$.ui.ddmanager.droppables[ scope ].push( this );
|
||||
},
|
||||
|
||||
_splice: function( drop ) {
|
||||
var i = 0;
|
||||
for ( ; i < drop.length; i++ ) {
|
||||
if ( drop[ i ] === this ) {
|
||||
drop.splice( i, 1 );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_destroy: function() {
|
||||
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
|
||||
|
||||
this._splice( drop );
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
|
||||
if ( key === "accept" ) {
|
||||
this.accept = typeof value === "function" ? value : function( d ) {
|
||||
return d.is( value );
|
||||
};
|
||||
} else if ( key === "scope" ) {
|
||||
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
|
||||
|
||||
this._splice( drop );
|
||||
this._addToManager( value );
|
||||
}
|
||||
|
||||
this._super( key, value );
|
||||
},
|
||||
|
||||
_activate: function( event ) {
|
||||
var draggable = $.ui.ddmanager.current;
|
||||
|
||||
this._addActiveClass();
|
||||
if ( draggable ) {
|
||||
this._trigger( "activate", event, this.ui( draggable ) );
|
||||
}
|
||||
},
|
||||
|
||||
_deactivate: function( event ) {
|
||||
var draggable = $.ui.ddmanager.current;
|
||||
|
||||
this._removeActiveClass();
|
||||
if ( draggable ) {
|
||||
this._trigger( "deactivate", event, this.ui( draggable ) );
|
||||
}
|
||||
},
|
||||
|
||||
_over: function( event ) {
|
||||
|
||||
var draggable = $.ui.ddmanager.current;
|
||||
|
||||
// Bail if draggable and droppable are same element
|
||||
if ( !draggable || ( draggable.currentItem ||
|
||||
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
|
||||
draggable.element ) ) ) {
|
||||
this._addHoverClass();
|
||||
this._trigger( "over", event, this.ui( draggable ) );
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_out: function( event ) {
|
||||
|
||||
var draggable = $.ui.ddmanager.current;
|
||||
|
||||
// Bail if draggable and droppable are same element
|
||||
if ( !draggable || ( draggable.currentItem ||
|
||||
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
|
||||
draggable.element ) ) ) {
|
||||
this._removeHoverClass();
|
||||
this._trigger( "out", event, this.ui( draggable ) );
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_drop: function( event, custom ) {
|
||||
|
||||
var draggable = custom || $.ui.ddmanager.current,
|
||||
childrenIntersection = false;
|
||||
|
||||
// Bail if draggable and droppable are same element
|
||||
if ( !draggable || ( draggable.currentItem ||
|
||||
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.element
|
||||
.find( ":data(ui-droppable)" )
|
||||
.not( ".ui-draggable-dragging" )
|
||||
.each( function() {
|
||||
var inst = $( this ).droppable( "instance" );
|
||||
if (
|
||||
inst.options.greedy &&
|
||||
!inst.options.disabled &&
|
||||
inst.options.scope === draggable.options.scope &&
|
||||
inst.accept.call(
|
||||
inst.element[ 0 ], ( draggable.currentItem || draggable.element )
|
||||
) &&
|
||||
$.ui.intersect(
|
||||
draggable,
|
||||
$.extend( inst, { offset: inst.element.offset() } ),
|
||||
inst.options.tolerance, event
|
||||
)
|
||||
) {
|
||||
childrenIntersection = true;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
if ( childrenIntersection ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this.accept.call( this.element[ 0 ],
|
||||
( draggable.currentItem || draggable.element ) ) ) {
|
||||
this._removeActiveClass();
|
||||
this._removeHoverClass();
|
||||
|
||||
this._trigger( "drop", event, this.ui( draggable ) );
|
||||
return this.element;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
ui: function( c ) {
|
||||
return {
|
||||
draggable: ( c.currentItem || c.element ),
|
||||
helper: c.helper,
|
||||
position: c.position,
|
||||
offset: c.positionAbs
|
||||
};
|
||||
},
|
||||
|
||||
// Extension points just to make backcompat sane and avoid duplicating logic
|
||||
// TODO: Remove in 1.14 along with call to it below
|
||||
_addHoverClass: function() {
|
||||
this._addClass( "ui-droppable-hover" );
|
||||
},
|
||||
|
||||
_removeHoverClass: function() {
|
||||
this._removeClass( "ui-droppable-hover" );
|
||||
},
|
||||
|
||||
_addActiveClass: function() {
|
||||
this._addClass( "ui-droppable-active" );
|
||||
},
|
||||
|
||||
_removeActiveClass: function() {
|
||||
this._removeClass( "ui-droppable-active" );
|
||||
}
|
||||
} );
|
||||
|
||||
$.ui.intersect = ( function() {
|
||||
function isOverAxis( x, reference, size ) {
|
||||
return ( x >= reference ) && ( x < ( reference + size ) );
|
||||
}
|
||||
|
||||
return function( draggable, droppable, toleranceMode, event ) {
|
||||
|
||||
if ( !droppable.offset ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var x1 = ( draggable.positionAbs ||
|
||||
draggable.position.absolute ).left + draggable.margins.left,
|
||||
y1 = ( draggable.positionAbs ||
|
||||
draggable.position.absolute ).top + draggable.margins.top,
|
||||
x2 = x1 + draggable.helperProportions.width,
|
||||
y2 = y1 + draggable.helperProportions.height,
|
||||
l = droppable.offset.left,
|
||||
t = droppable.offset.top,
|
||||
r = l + droppable.proportions().width,
|
||||
b = t + droppable.proportions().height;
|
||||
|
||||
switch ( toleranceMode ) {
|
||||
case "fit":
|
||||
return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
|
||||
case "intersect":
|
||||
return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
|
||||
x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
|
||||
t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
|
||||
y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
|
||||
case "pointer":
|
||||
return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
|
||||
isOverAxis( event.pageX, l, droppable.proportions().width );
|
||||
case "touch":
|
||||
return (
|
||||
( y1 >= t && y1 <= b ) || // Top edge touching
|
||||
( y2 >= t && y2 <= b ) || // Bottom edge touching
|
||||
( y1 < t && y2 > b ) // Surrounded vertically
|
||||
) && (
|
||||
( x1 >= l && x1 <= r ) || // Left edge touching
|
||||
( x2 >= l && x2 <= r ) || // Right edge touching
|
||||
( x1 < l && x2 > r ) // Surrounded horizontally
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} )();
|
||||
|
||||
/*
|
||||
This manager tracks offsets of draggables and droppables
|
||||
*/
|
||||
$.ui.ddmanager = {
|
||||
current: null,
|
||||
droppables: { "default": [] },
|
||||
prepareOffsets: function( t, event ) {
|
||||
|
||||
var i, j,
|
||||
m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
|
||||
type = event ? event.type : null, // workaround for #2317
|
||||
list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
|
||||
|
||||
droppablesLoop: for ( i = 0; i < m.length; i++ ) {
|
||||
|
||||
// No disabled and non-accepted
|
||||
if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
|
||||
( t.currentItem || t.element ) ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out elements in the current dragged item
|
||||
for ( j = 0; j < list.length; j++ ) {
|
||||
if ( list[ j ] === m[ i ].element[ 0 ] ) {
|
||||
m[ i ].proportions().height = 0;
|
||||
continue droppablesLoop;
|
||||
}
|
||||
}
|
||||
|
||||
m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
|
||||
if ( !m[ i ].visible ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Activate the droppable if used directly from draggables
|
||||
if ( type === "mousedown" ) {
|
||||
m[ i ]._activate.call( m[ i ], event );
|
||||
}
|
||||
|
||||
m[ i ].offset = m[ i ].element.offset();
|
||||
m[ i ].proportions( {
|
||||
width: m[ i ].element[ 0 ].offsetWidth,
|
||||
height: m[ i ].element[ 0 ].offsetHeight
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
drop: function( draggable, event ) {
|
||||
|
||||
var dropped = false;
|
||||
|
||||
// Create a copy of the droppables in case the list changes during the drop (#9116)
|
||||
$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
|
||||
|
||||
if ( !this.options ) {
|
||||
return;
|
||||
}
|
||||
if ( !this.options.disabled && this.visible &&
|
||||
$.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
|
||||
dropped = this._drop.call( this, event ) || dropped;
|
||||
}
|
||||
|
||||
if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
|
||||
( draggable.currentItem || draggable.element ) ) ) {
|
||||
this.isout = true;
|
||||
this.isover = false;
|
||||
this._deactivate.call( this, event );
|
||||
}
|
||||
|
||||
} );
|
||||
return dropped;
|
||||
|
||||
},
|
||||
dragStart: function( draggable, event ) {
|
||||
|
||||
// Listen for scrolling so that if the dragging causes scrolling the position of the
|
||||
// droppables can be recalculated (see #5003)
|
||||
draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
|
||||
if ( !draggable.options.refreshPositions ) {
|
||||
$.ui.ddmanager.prepareOffsets( draggable, event );
|
||||
}
|
||||
} );
|
||||
},
|
||||
drag: function( draggable, event ) {
|
||||
|
||||
// If you have a highly dynamic page, you might try this option. It renders positions
|
||||
// every time you move the mouse.
|
||||
if ( draggable.options.refreshPositions ) {
|
||||
$.ui.ddmanager.prepareOffsets( draggable, event );
|
||||
}
|
||||
|
||||
// Run through all droppables and check their positions based on specific tolerance options
|
||||
$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
|
||||
|
||||
if ( this.options.disabled || this.greedyChild || !this.visible ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var parentInstance, scope, parent,
|
||||
intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
|
||||
c = !intersects && this.isover ?
|
||||
"isout" :
|
||||
( intersects && !this.isover ? "isover" : null );
|
||||
if ( !c ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.options.greedy ) {
|
||||
|
||||
// find droppable parents with same scope
|
||||
scope = this.options.scope;
|
||||
parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
|
||||
return $( this ).droppable( "instance" ).options.scope === scope;
|
||||
} );
|
||||
|
||||
if ( parent.length ) {
|
||||
parentInstance = $( parent[ 0 ] ).droppable( "instance" );
|
||||
parentInstance.greedyChild = ( c === "isover" );
|
||||
}
|
||||
}
|
||||
|
||||
// We just moved into a greedy child
|
||||
if ( parentInstance && c === "isover" ) {
|
||||
parentInstance.isover = false;
|
||||
parentInstance.isout = true;
|
||||
parentInstance._out.call( parentInstance, event );
|
||||
}
|
||||
|
||||
this[ c ] = true;
|
||||
this[ c === "isout" ? "isover" : "isout" ] = false;
|
||||
this[ c === "isover" ? "_over" : "_out" ].call( this, event );
|
||||
|
||||
// We just moved out of a greedy child
|
||||
if ( parentInstance && c === "isout" ) {
|
||||
parentInstance.isout = false;
|
||||
parentInstance.isover = true;
|
||||
parentInstance._over.call( parentInstance, event );
|
||||
}
|
||||
} );
|
||||
|
||||
},
|
||||
dragStop: function( draggable, event ) {
|
||||
draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
|
||||
|
||||
// Call prepareOffsets one final time since IE does not fire return scroll events when
|
||||
// overflow was caused by drag (see #5003)
|
||||
if ( !draggable.options.refreshPositions ) {
|
||||
$.ui.ddmanager.prepareOffsets( draggable, event );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// DEPRECATED
|
||||
// TODO: switch return back to widget declaration at top of file when this is removed
|
||||
if ( $.uiBackCompat !== false ) {
|
||||
|
||||
// Backcompat for activeClass and hoverClass options
|
||||
$.widget( "ui.droppable", $.ui.droppable, {
|
||||
options: {
|
||||
hoverClass: false,
|
||||
activeClass: false
|
||||
},
|
||||
_addActiveClass: function() {
|
||||
this._super();
|
||||
if ( this.options.activeClass ) {
|
||||
this.element.addClass( this.options.activeClass );
|
||||
}
|
||||
},
|
||||
_removeActiveClass: function() {
|
||||
this._super();
|
||||
if ( this.options.activeClass ) {
|
||||
this.element.removeClass( this.options.activeClass );
|
||||
}
|
||||
},
|
||||
_addHoverClass: function() {
|
||||
this._super();
|
||||
if ( this.options.hoverClass ) {
|
||||
this.element.addClass( this.options.hoverClass );
|
||||
}
|
||||
},
|
||||
_removeHoverClass: function() {
|
||||
this._super();
|
||||
if ( this.options.hoverClass ) {
|
||||
this.element.removeClass( this.options.hoverClass );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return $.ui.droppable;
|
||||
|
||||
} );
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,72 @@
|
||||
/*!
|
||||
* jQuery UI Effects Blind 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Blind Effect
|
||||
//>>group: Effects
|
||||
//>>description: Blinds the element.
|
||||
//>>docs: http://api.jqueryui.com/blind-effect/
|
||||
//>>demos: http://jqueryui.com/effect/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./effect"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
return $.effects.define( "blind", "hide", function( options, done ) {
|
||||
var map = {
|
||||
up: [ "bottom", "top" ],
|
||||
vertical: [ "bottom", "top" ],
|
||||
down: [ "top", "bottom" ],
|
||||
left: [ "right", "left" ],
|
||||
horizontal: [ "right", "left" ],
|
||||
right: [ "left", "right" ]
|
||||
},
|
||||
element = $( this ),
|
||||
direction = options.direction || "up",
|
||||
start = element.cssClip(),
|
||||
animate = { clip: $.extend( {}, start ) },
|
||||
placeholder = $.effects.createPlaceholder( element );
|
||||
|
||||
animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
|
||||
|
||||
if ( options.mode === "show" ) {
|
||||
element.cssClip( animate.clip );
|
||||
if ( placeholder ) {
|
||||
placeholder.css( $.effects.clipToBox( animate ) );
|
||||
}
|
||||
|
||||
animate.clip = start;
|
||||
}
|
||||
|
||||
if ( placeholder ) {
|
||||
placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
|
||||
}
|
||||
|
||||
element.animate( animate, {
|
||||
queue: false,
|
||||
duration: options.duration,
|
||||
easing: options.easing,
|
||||
complete: done
|
||||
} );
|
||||
} );
|
||||
|
||||
} );
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* jQuery UI Effects Blind 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./effect"],e):e(jQuery)}(function(r){"use strict";return r.effects.define("blind","hide",function(e,t){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},o=r(this),c=e.direction||"up",n=o.cssClip(),f={clip:r.extend({},n)},l=r.effects.createPlaceholder(o);f.clip[i[c][0]]=f.clip[i[c][1]],"show"===e.mode&&(o.cssClip(f.clip),l&&l.css(r.effects.clipToBox(f)),f.clip=n),l&&l.animate(r.effects.clipToBox(f),e.duration,e.easing),o.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:t})})});
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*!
|
||||
* jQuery UI Effects Bounce 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Bounce Effect
|
||||
//>>group: Effects
|
||||
//>>description: Bounces an element horizontally or vertically n times.
|
||||
//>>docs: http://api.jqueryui.com/bounce-effect/
|
||||
//>>demos: http://jqueryui.com/effect/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./effect"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
return $.effects.define( "bounce", function( options, done ) {
|
||||
var upAnim, downAnim, refValue,
|
||||
element = $( this ),
|
||||
|
||||
// Defaults:
|
||||
mode = options.mode,
|
||||
hide = mode === "hide",
|
||||
show = mode === "show",
|
||||
direction = options.direction || "up",
|
||||
distance = options.distance,
|
||||
times = options.times || 5,
|
||||
|
||||
// Number of internal animations
|
||||
anims = times * 2 + ( show || hide ? 1 : 0 ),
|
||||
speed = options.duration / anims,
|
||||
easing = options.easing,
|
||||
|
||||
// Utility:
|
||||
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
|
||||
motion = ( direction === "up" || direction === "left" ),
|
||||
i = 0,
|
||||
|
||||
queuelen = element.queue().length;
|
||||
|
||||
$.effects.createPlaceholder( element );
|
||||
|
||||
refValue = element.css( ref );
|
||||
|
||||
// Default distance for the BIGGEST bounce is the outer Distance / 3
|
||||
if ( !distance ) {
|
||||
distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
|
||||
}
|
||||
|
||||
if ( show ) {
|
||||
downAnim = { opacity: 1 };
|
||||
downAnim[ ref ] = refValue;
|
||||
|
||||
// If we are showing, force opacity 0 and set the initial position
|
||||
// then do the "first" animation
|
||||
element
|
||||
.css( "opacity", 0 )
|
||||
.css( ref, motion ? -distance * 2 : distance * 2 )
|
||||
.animate( downAnim, speed, easing );
|
||||
}
|
||||
|
||||
// Start at the smallest distance if we are hiding
|
||||
if ( hide ) {
|
||||
distance = distance / Math.pow( 2, times - 1 );
|
||||
}
|
||||
|
||||
downAnim = {};
|
||||
downAnim[ ref ] = refValue;
|
||||
|
||||
// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
|
||||
for ( ; i < times; i++ ) {
|
||||
upAnim = {};
|
||||
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
|
||||
|
||||
element
|
||||
.animate( upAnim, speed, easing )
|
||||
.animate( downAnim, speed, easing );
|
||||
|
||||
distance = hide ? distance * 2 : distance / 2;
|
||||
}
|
||||
|
||||
// Last Bounce when Hiding
|
||||
if ( hide ) {
|
||||
upAnim = { opacity: 0 };
|
||||
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
|
||||
|
||||
element.animate( upAnim, speed, easing );
|
||||
}
|
||||
|
||||
element.queue( done );
|
||||
|
||||
$.effects.unshift( element, queuelen, anims + 1 );
|
||||
} );
|
||||
|
||||
} );
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* jQuery UI Effects Bounce 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./effect"],e):e(jQuery)}(function(l){"use strict";return l.effects.define("bounce",function(e,t){var i,n,c=l(this),f=e.mode,o="hide"===f,f="show"===f,u=e.direction||"up",a=e.distance,s=e.times||5,r=2*s+(f||o?1:0),d=e.duration/r,p=e.easing,h="up"===u||"down"===u?"top":"left",m="up"===u||"left"===u,y=0,e=c.queue().length;for(l.effects.createPlaceholder(c),u=c.css(h),a=a||c["top"==h?"outerHeight":"outerWidth"]()/3,f&&((n={opacity:1})[h]=u,c.css("opacity",0).css(h,m?2*-a:2*a).animate(n,d,p)),o&&(a/=Math.pow(2,s-1)),(n={})[h]=u;y<s;y++)(i={})[h]=(m?"-=":"+=")+a,c.animate(i,d,p).animate(n,d,p),a=o?2*a:a/2;o&&((i={opacity:0})[h]=(m?"-=":"+=")+a,c.animate(i,d,p)),c.queue(t),l.effects.unshift(c,e,1+r)})});
|
||||
@@ -0,0 +1,67 @@
|
||||
/*!
|
||||
* jQuery UI Effects Clip 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
//>>label: Clip Effect
|
||||
//>>group: Effects
|
||||
//>>description: Clips the element on and off like an old TV.
|
||||
//>>docs: http://api.jqueryui.com/clip-effect/
|
||||
//>>demos: http://jqueryui.com/effect/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define( [
|
||||
"jquery",
|
||||
"./effect"
|
||||
], factory );
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
return $.effects.define( "clip", "hide", function( options, done ) {
|
||||
var start,
|
||||
animate = {},
|
||||
element = $( this ),
|
||||
direction = options.direction || "vertical",
|
||||
both = direction === "both",
|
||||
horizontal = both || direction === "horizontal",
|
||||
vertical = both || direction === "vertical";
|
||||
|
||||
start = element.cssClip();
|
||||
animate.clip = {
|
||||
top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
|
||||
right: horizontal ? ( start.right - start.left ) / 2 : start.right,
|
||||
bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
|
||||
left: horizontal ? ( start.right - start.left ) / 2 : start.left
|
||||
};
|
||||
|
||||
$.effects.createPlaceholder( element );
|
||||
|
||||
if ( options.mode === "show" ) {
|
||||
element.cssClip( animate.clip );
|
||||
animate.clip = start;
|
||||
}
|
||||
|
||||
element.animate( animate, {
|
||||
queue: false,
|
||||
duration: options.duration,
|
||||
easing: options.easing,
|
||||
complete: done
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* jQuery UI Effects Clip 1.13.2
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery","./effect"],t):t(jQuery)}(function(r){"use strict";return r.effects.define("clip","hide",function(t,e){var i={},o=r(this),c=t.direction||"vertical",n="both"===c,f=n||"horizontal"===c,n=n||"vertical"===c,c=o.cssClip();i.clip={top:n?(c.bottom-c.top)/2:c.top,right:f?(c.right-c.left)/2:c.right,bottom:n?(c.bottom-c.top)/2:c.bottom,left:f?(c.right-c.left)/2:c.left},r.effects.createPlaceholder(o),"show"===t.mode&&(o.cssClip(i.clip),i.clip=c),o.animate(i,{queue:!1,duration:t.duration,easing:t.easing,complete:e})})});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user