Skip to content
Browse files

Initial commit of v0.4 copied from WP.com VIP SVN repo

  • Loading branch information...
0 parents commit 000cb76f0cf53812bc81bb28f25d08861a8aae65 @mjangda mjangda committed Sep 4, 2012
BIN css/images/drag.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/images/gray-grad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/images/wpspin_light.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_glass_75_dadada_1x400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-icons_222222_256x240.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-icons_2e83ff_256x240.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-icons_454545_256x240.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-icons_888888_256x240.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN css/jquery-ui/smoothness/images/ui-icons_cd0a0a_256x240.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
347 css/jquery-ui/smoothness/jquery-ui-zoninator.css
@@ -0,0 +1,347 @@
+/*
+ * jQuery UI CSS Framework 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*
+ * jQuery UI CSS Framework 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
+ * jQuery UI Autocomplete 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.9
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
278 css/zoninator.css
@@ -0,0 +1,278 @@
+.wrap.zoninator-page {
+ width: 95%;
+}
+#zoninator-wrap {
+ overflow: hidden;
+ clear: both;
+ position: relative;
+ margin-top: 15px;
+}
+ #zoninator-wrap .delete {
+ color: #BC0B0B;
+ }
+.zone-col {
+ float: left;
+ width: 48%;
+}
+
+/** Tabs **/
+/** Blatantly stolen from nav-menu.dev.css **/
+.zone-tabs-container {
+}
+ .zone-tabs-nav-wrapper {
+ width: 92%;
+ position: relative;
+ float: left;
+ }
+ .zone-tab-new {
+ float: right;
+ margin-right: 1%;
+ margin-bottom: -1px;
+ }
+ .zone-tabs-container .nav-tabs-arrow {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ }
+ .zone-tabs-container .nav-tabs-nav {
+ margin: 0 20px;
+ }
+ .zone-tabs-container .nav-tabs-arrow {
+ width: 10px;
+ padding: 0 5px 4px;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ line-height: 22px;
+ font-size: 18px;
+ text-shadow: 0 1px 0 #fff;
+ }
+ .zone-tabs-container .nav-tabs-arrow a { color: #C1C1C1; }
+ .zone-tabs-container .nav-tabs-arrow a:hover { color: #D54E21; }
+ .zone-tabs-container .nav-tabs-arrow a:active { color: #464646; }
+ .zone-tabs-container .nav-tabs-arrow-left {
+ left: 0;
+ }
+ .zone-tabs-container .nav-tabs-arrow-right {
+ right: 0;
+ text-align: right;
+ }
+ .zone-tabs-container .nav-tabs-wrapper {
+ width: 100%;
+ height: 28px;
+ margin-bottom: -1px;
+ overflow: hidden;
+ }
+ .zone-tabs-container .nav-tabs {
+ padding-left: 20px;
+ padding-right: 10px;
+ }
+ .js .zone-tabs-container .nav-tabs {
+ float: left;
+ margin-left: 0px;
+ margin-right: -400px;
+ }
+ .zone-tabs-container .nav-tab {
+ margin-bottom: 0;
+ background: #f4f4f4;
+ font-weight: bold;
+ border-color: #dfdfdf;
+ }
+ .zone-tabs-container .nav-tab-active {
+ border-bottom: 1px solid #ececec;
+ background: #ececec;
+ }
+
+/** Edit **/
+#zone-edit-wrapper {
+ padding: 10px;
+ clear: both;
+ overflow: hidden;
+ border: 1px solid #ccc;
+ -moz-border-radius: 4px; -wekbit-border-radius: 4px; -ms-border-radius: 4px; border-radius: 4px;
+ background: url(images/gray-grad.png) repeat-x scroll left top #dfdfdf;
+}
+ #zone-edit-wrapper .form-wrap {
+ margin: 0;
+ }
+ #zone-edit-wrapper .form-field {
+ padding: 0;
+ }
+ #zone-edit-wrapper .form-field.error {
+ padding: 0 10px 5px;
+ }
+ #zone-edit-wrapper .form-field input,
+ #zone-edit-wrapper .form-field textarea {
+ width: 98%;
+ }
+ #zone-edit-wrapper .submit-field {
+ width: 95%;
+ }
+ #zone-edit-wrapper .submit-field .submitdelete {
+ float: right;
+ }
+ #zone-info-readonly label {
+ font-weight: bold;
+ }
+ #zone-info-readonly span {
+ }
+
+/** Zone Posts **/
+.zone-posts-col {
+ background: #fff;
+ border: 1px solid #ccc;
+ -moz-border-radius: 4px; -wekbit-border-radius: 4px; -ms-border-radius: 4px; border-radius: 4px;
+
+ float: right;
+ padding: 10px;
+}
+ .zone-posts-col h3 {
+ margin: 3px 0;
+ }
+ .zone-posts-wrapper.loading {
+ background-image: url(images/wpspin_light.gif);
+ background-position: right top;
+ background-repeat: no-repeat;
+ }
+ .zone-posts-wrapper.readonly {
+ }
+ .zone-posts-wrapper.readonly .zone-search-wrapper,
+ .zone-posts-wrapper.readonly .row-actions {
+ display: none !important;
+ }
+ .zone-posts-wrapper.readonly .zone-post {
+ cursor: default !important;
+ }
+ .zone-posts-wrapper.readonly .zone-post:hover .zone-post-position {
+ background: none;
+ text-indent: 0;
+ }
+
+.zone-posts-list {
+ margin: 10px 0;
+}
+ .zone-posts-list .ui-state-highlight {
+ margin-bottom: 5px;
+ -moz-border-radius: 4px; -wekbit-border-radius: 4px; -ms-border-radius: 4px; border-radius: 4px;
+ }
+ .zone-posts-list.ui-sortable .zone-post {
+ cursor: move;
+ }
+ .zone-post {
+ padding: 5px 0 5px 10px;
+ margin-bottom: 5px;
+ font-size: 12px;
+ line-height: 15px;
+ font-weight: bold;
+ color: #444;
+ overflow: hidden;
+
+ border: 1px dotted #eee;
+ -moz-border-radius: 4px; -wekbit-border-radius: 4px; -ms-border-radius: 4px; border-radius: 4px;
+
+ background: #f5f5f5;
+ }
+ .zone-post table {
+ width: 100%;
+ }
+ .zone-post-col {
+ }
+ .zone-post:hover .zone-post-position {
+ background: url(images/drag.png) no-repeat left center;
+ text-indent: -9999px;
+ }
+ .zone-post-position {
+ font-size: 24px;
+ line-height: 32px;
+ font-weight: normal;
+ text-align: center;
+ width: 32px;
+ }
+ /*
+ .zone-post-handle {
+ display: block;
+ background: url(images/drag.png) no-repeat center center;
+ width: 32px;
+ height: 32px;
+
+ float: right;
+ visibility: hidden;
+ }
+ */
+ .zone-post-status {
+ color: #999;
+ }
+ .zone-post .row-actions {
+ font-size: 11px;
+ font-weight: normal;
+ }
+ .zone-post:hover .row-actions,
+ .zone-post.loading .row-actions,
+ .zone-post:hover .zone-post-handle,
+ .zone-post.loading .zone-post-handle {
+ visibility: visible;
+ }
+ .zone-post.loading .zone-post-position {
+ background-image: url(images/wpspin_light.gif);
+ text-indent: -9999px;
+ }
+ .zone-search-wrapper {
+ padding: 7px 0;
+ border-bottom: 1px dotted #999;
+ }
+ #zone-post-search {
+ width: 99%;
+ }
+ #zone-post-latest {
+ width: 98%;
+ }
+
+/** Autocomplete **/
+.ui-autocomplete-input.loading {
+ background-image: url(images/wpspin_light.gif);
+ background-repeat: no-repeat;
+ background-position: right center;
+}
+.ui-autocomplete {
+ min-width: 330px;
+ max-width: 600px;
+ font-size: 13px;
+ line-height: 17px;
+}
+ .ui-autocomplete .ui-corner-all {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ border-bottom: 1px dotted #eee;
+ cursor: pointer;
+ overflow: hidden;
+ }
+ .ui-autocomplete .title {
+ display: block;
+ width: 80%;
+ float: left;
+ }
+ .ui-autocomplete .date {
+ text-transform: uppercase;
+ color: #666;
+ font-size: 11px;
+ clear: both;
+ float: left;
+ }
+ .ui-autocomplete .type {
+ text-transform: uppercase;
+ color: #666;
+ font-size: 11px;
+ width: 19%;
+ margin-left: 1%;
+ float: right;
+ text-align: right;
+ }
+ .ui-autocomplete .status {
+ font-size: 10px;
+ width: 19%;
+ margin-left: 1%;
+ float: right;
+ text-align: right;
+ }
87 functions.php
@@ -0,0 +1,87 @@
+<?php
+
+function z_get_zoninator() {
+ global $zoninator;
+ return $zoninator;
+}
+
+/**
+ * Get a list of all zones
+ * @return array List of all zones
+ */
+function z_get_zones() {
+ return z_get_zoninator()->get_zones();
+}
+
+/**
+ * @param $zone int|string ID or Slug of the zone
+ * @return array Zone object
+ */
+function z_get_zone( $zone ) {
+ return z_get_zoninator()->get_zone( $zone );
+}
+
+/**
+ * @param $zone int|string ID or Slug of the zone
+ * @return array List of orders post objects
+ */
+function z_get_posts_in_zone( $zone, $args = array() ) {
+ // TODO: return only published posts by default
+ // TODO: ability to grab draft as well
+
+ return z_get_zoninator()->get_zone_posts( $zone );
+}
+
+/**
+ * @param $zone int|string ID or Slug of the zone
+ * @return array List of orders post objects
+ */
+function z_get_zone_query( $zone ) {
+ return z_get_zoninator()->get_zone_query( $zone );
+}
+
+/**
+ * @param $zone int|string ID or Slug of the zone
+ * @param $post_id int ID of the post (or, null if in The Loop)
+ * @return array|false Returns next post relative to post_id for the given zone
+ */
+function z_get_next_post_in_zone( $zone, $post_id = 0 ) {
+ $post_id = z_get_loop_post_id_or_default( $post_id );
+ return z_get_zoninator()->get_next_post_in_zone( $zone, $post_id );
+}
+
+/**
+ * @param $zone int|string ID or Slug of the zone
+ * @param $post_id int ID of the post (or, null if in The Loop)
+ * @return array|false Returns previous post relative to post_id for the given zone
+ */
+function z_get_prev_post_in_zone( $zone, $post_id = 0 ) {
+ $post_id = z_get_loop_post_id_or_default( $post_id );
+ return z_get_zoninator()->get_prev_post_in_zone( $zone, $post_id );
+}
+
+/**
+ * @param $post_id int ID of the post (or, null if in The Loop)
+ * @return array List of of zones that the given post is in
+ */
+function z_get_post_zones( $post_id = 0 ) {
+ $post_id = z_get_loop_post_id_or_default( $post_id );
+ return z_get_zoninator()->get_zones_for_post( $post_id );
+}
+
+function z_get_loop_post_id_or_default( $post_id = 0 ) {
+ if( ! $post_id ) {
+ global $post;
+ if( $post && isset( $post->ID ) ) $post_id = $post->ID;
+ }
+ return $post_id;
+}
+
+/**
+ * Handy function to disable the locking mechanism
+ */
+function z_disable_zoninator_locks() {
+ return -1;
+}
+
+// (Should probably publicly expose set_zone_posts as well, e.g. if we wanted to add a metabox on the Edit Post page)
546 js/zoninator.js
@@ -0,0 +1,546 @@
+var zoninator = {}
+
+;(function($, window, undefined) {
+
+ zoninator.init = function() {
+ zoninator.autocompleteCache = {}
+ zoninator.autocompleteAjax = {}
+ zoninator.$zonePostsList = $('.zone-posts-list');
+ zoninator.$zonePostsWrap = $('.zone-posts-wrapper');
+ zoninator.$zonePostSearch = $("#zone-post-search");
+ zoninator.$zonePostLatest = $("#zone-post-latest");
+ zoninator.updatePostOrder();
+
+ zoninator.initTabManager();
+
+ // Bind actions to buttons
+ zoninator.initZonePost(zoninator.$zonePostsList.children());
+
+ // Initialize sortable
+ if(!zoninator.$zonePostsWrap.hasClass('readonly')) {
+ zoninator.$zonePostsList.sortable({
+ stop: zoninator.reorderPosts
+ , placeholder: 'ui-state-highlight'
+ , forcePlaceholderSize: true
+ //, handle: '.zone-post-handle'
+ });
+ }
+
+ // Bind loading events
+ zoninator.$zonePostsWrap
+ .bind('loading.start', function() {
+ $(this).addClass('loading');
+ })
+ .bind('loading.end', function() {
+ $(this).removeClass('loading');
+ });
+
+ // Validate form
+ // TODO: This is really simplistic validation; beef it up a bit.
+ $('#zone-info').submit(function(e) {
+ var $form = $(this);
+ var $name = $form.find('input[name="name"]');
+ if( !$name.val().trim() ) {
+ $name.closest( '.zone-field' ).addClass('error');
+ return false;
+ } else {
+ $name.closest( '.zone-field' ).removeClass('error');
+ }
+ });
+
+ zoninator.$zonePostLatest.change(function() {
+ var $this = $(this),
+ post_id = $this.val();
+ if ( post_id ) {
+ zoninator.addPost( post_id );
+ $this.find( '[value="' + post_id + '"]' ).remove();
+ }
+ });
+
+ // Initialize autocomplete
+ if(zoninator.$zonePostSearch.length) {
+ zoninator.$zonePostSearch
+ .bind('loading.start', function(e) {
+ $(this).addClass('loading');
+ })
+ .bind('loading.end', function(e) {
+ $(this).removeClass('loading');
+ })
+ .autocomplete({
+ minLength: 3
+ // Remote source with caching
+ , source: function( request, response ) {
+ var term = request.term;
+ if ( term in zoninator.autocompleteCache ) {
+ response( zoninator.autocompleteCache[ term ] );
+ zoninator.$zonePostSearch.trigger('loading.end');
+ return;
+ }
+
+ // Append more request vars
+ request.action = zoninator.getAjaxAction('search_posts');
+ request.exclude = zoninator.getZonePostIds();
+
+ zoninator.autocompleteAjax = $.getJSON( ajaxurl, request, function( data, status, xhr ) {
+ zoninator.autocompleteCache[ term ] = data;
+ if ( xhr === zoninator.autocompleteAjax ) {
+ response( data );
+ }
+ zoninator.$zonePostSearch.trigger('loading.end');
+ });
+ }
+ , select: function( e, ui ) {
+ zoninator.addPost(ui.item.post_id);
+ }
+ , search: function( e, ui ) {
+ zoninator.$zonePostSearch.trigger('loading.start');
+ }
+ })
+ .data( 'autocomplete' )._renderItem = function( ul, item ) {
+ var content = '<a>'
+ + '<span class="title">' + item.title + '</span>'
+ + '<span class="type">' + item.post_type + '</span>'
+ + '<span class="date">' + item.date + '</span>'
+ + '<span class="status">' + item.post_status + '</span>'
+ + '</a>';
+ return $( '<li></li>' )
+ .data( 'item.autocomplete', item )
+ .append( content )
+ .appendTo( ul )
+ ;
+ }
+ ;
+ }
+
+ // Initialize lock heartbeat
+ if( zoninator.getZoneId() && ! $('#zone-locked').length ) {
+ zoninator.currentLockPeriod = 0;
+ zoninator.heartbeatInterval = parseInt( zoninatorOptions.zoneLockPeriod );
+ zoninator.maxLockPeriod = parseInt( zoninatorOptions.zoneLockPeriodMax );
+
+ if( zoninator.heartbeatInterval > 0 && zoninator.maxLockPeriod != -1) {
+ zoninator.heartbeatInterval = zoninator.heartbeatInterval * 1000;
+ zoninator.maxLockPeriod = zoninator.maxLockPeriod * 1000;
+
+ zoninator.updateLock();
+ }
+ }
+
+ // TODO: move / copy posts to zones
+ }
+
+ zoninator.addPost = function(postId) {
+
+ zoninator.$zonePostSearch.trigger('loading.start');
+
+ zoninator.ajax('add_post', {
+ zone_id: zoninator.getZoneId()
+ , post_id: postId
+ }, zoninator.addPostSuccessCallback);
+
+ }
+
+ zoninator.addPostSuccessCallback = function(returnData) {
+
+ zoninator.$zonePostSearch.trigger('loading.end');
+
+ // Add Post to List
+ var $post = $(returnData.content);
+ $post.hide()
+ .appendTo(zoninator.$zonePostsList)
+ .fadeIn()
+ ;
+
+ zoninator.initZonePost($post);
+
+ // Reorder Posts
+ zoninator.updatePostOrder(true);
+ }
+
+ zoninator.initZonePost = function($elem) {
+ $elem.bind('loading.start', function(e) {
+ $(this).addClass('loading');
+ }).bind('loading.end', function(e) {
+ $(this).removeClass('loading');
+ });
+
+ $elem.find('.delete').bind('click', function(e) {
+ e.preventDefault();
+ var postId = zoninator.getPostIdFromElem(this);
+ zoninator.removePost(postId);
+ });
+ }
+
+ zoninator.removePost = function(postId) {
+ zoninator.getPost(postId).trigger('loading.start');
+
+ zoninator.ajax('remove_post', {
+ zone_id: zoninator.getZoneId()
+ , post_id: postId
+ }, zoninator.removePostSuccessCallback);
+ }
+
+ zoninator.removePostSuccessCallback = function(returnData, originalData) {
+ var postId = originalData.post_id;
+
+ zoninator.getPost(postId).fadeOut('slow', function() {
+ $(this).remove();
+ if ( zoninator.getZonePostIds().length )
+ zoninator.updatePostOrder(true);
+ zoninator.$zonePostsWrap.trigger('loading.end');
+ });
+ }
+
+ zoninator.reorderPosts = function() {
+ // get list of post ids
+ var zoneId = zoninator.getZoneId()
+ , postIds = zoninator.getZonePostIds()
+ ;
+
+ // Reorder only if changed
+ if(!compareArrays(postIds, zoninator.getPostOrder())) {
+ var data = {
+ zone_id: zoneId
+ , posts: postIds
+ }
+
+ zoninator.$zonePostsWrap.trigger('loading.start');
+
+ // make ajax call to save order
+ zoninator.ajax('reorder_posts', data, zoninator.reorderPostsSuccessCallback);
+ }
+ }
+
+ zoninator.reorderPostsSuccessCallback = function(returnData, originalData) {
+ zoninator.$zonePostsWrap.trigger('loading.end');
+ zoninator.updatePostOrder(false);
+
+ // The user took some action so reset the lock period
+ zoninator.resetCurrentLockPeriod();
+ }
+
+ zoninator.updateLock = function() {
+ zoninator.ajax('update_lock', {
+ zone_id: zoninator.getZoneId()
+ }, function(returnData, originalData) {
+ zoninator.currentLockPeriod += zoninator.heartbeatInterval;
+
+ // We want to set a max to avoid people leaving their tabs open and then running away for long periods
+ if( zoninator.currentLockPeriod < zoninator.maxLockPeriod ) {
+ setTimeout(zoninator.updateLock, zoninator.heartbeatInterval);
+ } else {
+ alert(zoninatorOptions.errorZoneLockMax);
+ location.href = zoninatorOptions.adminUrl;
+ }
+ }, function(returnData, originalData) {
+ // Show alert and reload page to update lock
+ alert(zoninatorOptions.errorZoneLock);
+ location.reload();
+ });
+ }
+
+ zoninator.resetCurrentLockPeriod = function() {
+ zoninator.currentLockPeriod = 0;
+ }
+
+ zoninator.ajax = function(action, values, successCallback, errorCallback, params) {
+ var data = {
+ action: zoninator.getAjaxAction(action)
+ , _wpnonce: zoninator.getAjaxNonce()
+ }
+ data = $.extend({}, data, values);
+
+ var defaultParams = {
+ url: ajaxurl
+ , data: data
+ , dataType: 'json'
+ , type: 'POST'
+ , success: function(returnData) {
+ zoninator.ajaxSuccessCallback(returnData, data, successCallback, errorCallback);
+ }
+ , error: function(returnData) {
+ zoninator.ajaxErrorCallback(returnData, data, successCallback, errorCallback);
+ }
+ }
+ params = $.extend({}, defaultParams, params);
+
+ $.ajax(params);
+ }
+
+ zoninator.ajaxSuccessCallback = function(returnData, originalData, successCallback, errorCallback) {
+ if(typeof(returnData) === 'undefined' || !returnData.status) {
+ // If we didn't get a valid return, it's probably an error
+ return zoninator.ajaxErrorCallback(returnData, originalData, successCallback, errorCallback);
+ }
+
+ //console.log('ajaxSuccessCallback', returnData, originalData);
+
+ if(returnData.nonce)
+ zoninator.updateAjaxNonce(returnData.nonce);
+
+ if(typeof(successCallback) === 'function') {
+ return successCallback(returnData, originalData);
+ } else {
+ alert(returnData.content);
+ }
+ }
+
+ zoninator.ajaxErrorCallback = function(returnData, originalData, successCallback, errorCallback) {
+ if( typeof(returnData) === 'undefined' || !returnData ) {
+ returnData = {
+ status: 0
+ , content: zoninatorOptions.errorGeneral
+ }
+ }
+
+ //console.log('ajaxErrorCallback', returnData, originalData);
+
+ if(typeof(errorCallback) === 'function') {
+ return errorCallback(returnData, originalData);
+ } else {
+ if( typeof(returnData.content) === 'undefined' || !returnData.content )
+ returnData.content = zoninatorOptions.errorGeneral;
+ alert(returnData.content);
+ }
+ }
+
+ zoninator.updateAjaxNonce = function(action, nonce) {
+ zoninator.getAjaxNonceField(action).val(nonce);
+ }
+
+ zoninator.getAjaxNonce = function(action) {
+ return zoninator.getAjaxNonceField(action).val();
+ }
+ zoninator.getAjaxNonceField = function(action) {
+ action = action || zoninatorOptions.ajaxNonceAction;
+ return $('#' + action );
+ }
+
+ zoninator.getZoneId = function() {
+ return $('#zone_id').length ? $('#zone_id').val() : 0;
+ }
+
+ zoninator.getZonePosts = function() {
+ return zoninator.$zonePostsList.children();
+ }
+
+ zoninator.getPost = function(postId) {
+ return $('#zone-post-' + postId);
+ }
+
+ zoninator.getPostIdFromElem = function(elem) {
+ return $(elem).closest('.zone-post').attr('data-post-id');
+ }
+
+ zoninator.getZonePostIds = function() {
+ var ids = []
+ , $posts = zoninator.getZonePosts();
+ $posts.find('[name="zone-post-id"]').each(function(i, elem) {
+ ids.push(elem.value);
+ });
+ return ids;
+ }
+
+ zoninator.getPostOrder = function() {
+ if(!$.isArray(zoninator.currentPostOrder))
+ zoninator.updatePostOrder();
+ return zoninator.currentPostOrder;
+ }
+
+ zoninator.updatePostOrder = function(save) {
+ if(save)
+ zoninator.reorderPosts();
+
+ zoninator.currentPostOrder = zoninator.getZonePostIds();
+ zoninator.renumberPosts();
+ }
+
+ zoninator.renumberPosts = function() {
+ var $numbers = zoninator.$zonePostsList.find('.zone-post-position');
+ $numbers.each(function(i, elem) {
+ $(elem).text(i + 1);
+ });
+ }
+
+ zoninator.getAjaxAction = function(action) {
+ return 'zoninator_' + action;
+ }
+
+ zoninator.emptyFunc = function() {}
+
+ /**
+ * compareArrays - Compares two arrays!
+ *
+ * Copyright (c) David
+ * http://stackoverflow.com/questions/1773069/using-jquery-to-compare-two-arrays/1773172#1773172
+ *
+ * Some mods by Mohammad Jangda
+ *
+ * @param Array First Array
+ * @param Array Second Array
+ * @param bool Sort the arrays before comparing?
+ *
+ */
+ var compareArrays = function(arr1, arr2, sort) {
+ if (arr1.length != arr2.length) return false;
+
+ if(sort) {
+ arr1 = arr1.sort(),
+ arr2 = arr2.sort();
+ }
+ for (var i = 0; arr2[i]; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ // Stolen from nav-menu.js
+ zoninator.initTabManager = function() {
+ var fixed = $('.nav-tabs-wrapper'),
+ fluid = fixed.children('.nav-tabs'),
+ active = fluid.children('.nav-tab-active'),
+ tabs = fluid.children('.nav-tab'),
+ tabsWidth = 0,
+ fixedRight, fixedLeft,
+ arrowLeft, arrowRight, resizeTimer, css = {},
+ marginFluid = 'margin-left',
+ marginFixed = 'margin-right',
+ msPerPx = 2;
+
+ /**
+ * Refreshes the menu tabs.
+ * Will show and hide arrows where necessary.
+ * Scrolls to the active tab by default.
+ *
+ * @param savePosition {boolean} Optional. Prevents scrolling so
+ * that the current position is maintained. Default false.
+ **/
+ refreshMenuTabs = function( savePosition ) {
+ var fixedWidth = fixed.width(),
+ margin = 0, css = {};
+ fixedLeft = fixed.offset().left;
+ fixedRight = fixedLeft + fixedWidth;
+
+ if( !savePosition )
+ active.makeTabVisible();
+
+ // Prevent space from building up next to the last tab if there's more to show
+ var $lastTab = tabs.last();
+ if( $lastTab.length && $lastTab.isTabVisible() ) {
+ margin = fixed.width() - tabsWidth;
+ margin = margin > 0 ? 0 : margin;
+ css[marginFluid] = margin + 'px';
+ fluid.animate( css, 100, "linear" );
+ }
+
+ // Show the arrows only when necessary
+ if( fixedWidth > tabsWidth )
+ arrowLeft.add( arrowRight ).hide();
+ else
+ arrowLeft.add( arrowRight ).show();
+ }
+
+ $.fn.extend({
+ makeTabVisible : function() {
+ var t = this.eq(0), left, right, css = {}, shift = 0;
+
+ if( ! t.length ) return this;
+
+ left = t.offset().left;
+ right = left + t.outerWidth();
+
+ if( right > fixedRight )
+ shift = fixedRight - right;
+ else if ( left < fixedLeft )
+ shift = fixedLeft - left;
+
+ if( ! shift ) return this;
+
+ css[marginFluid] = "+=" + shift + 'px';
+ fluid.animate( css, Math.abs( shift ) * msPerPx, "linear" );
+ return this;
+ },
+ isTabVisible : function() {
+ var t = this.eq(0),
+ left = t.offset().left,
+ right = left + t.outerWidth();
+ return ( right <= fixedRight && left >= fixedLeft ) ? true : false;
+ }
+ });
+
+ // Find the width of all tabs
+ tabs.each(function(){
+ tabsWidth += $(this).outerWidth(true);
+ });
+
+ // Set up fixed margin for overflow, unset padding
+ css['padding'] = 0;
+ css[marginFixed] = (-1 * tabsWidth) + 'px';
+ fluid.css( css );
+
+ // Build tab navigation
+ arrowLeft = $('<div class="nav-tabs-arrow nav-tabs-arrow-left"><a>&laquo;</a></div>');
+ arrowRight = $('<div class="nav-tabs-arrow nav-tabs-arrow-right"><a>&raquo;</a></div>');
+ // Attach to the document
+ fixed.wrap('<div class="nav-tabs-nav"/>').parent().prepend( arrowLeft ).append( arrowRight );
+ // Set the menu tabs
+ refreshMenuTabs();
+ // Make sure the tabs reset on resize
+ $(window).resize(function() {
+ if( resizeTimer ) clearTimeout(resizeTimer);
+ resizeTimer = setTimeout( refreshMenuTabs, 200);
+ });
+
+ // Build arrow functions
+ $.each([{
+ arrow : arrowLeft,
+ next : "next",
+ last : "first",
+ operator : "+="
+ },{
+ arrow : arrowRight,
+ next : "prev",
+ last : "last",
+ operator : "-="
+ }], function(){
+ var that = this;
+ this.arrow.mousedown(function(){
+ var marginFluidVal = Math.abs( parseInt( fluid.css(marginFluid) ) ),
+ shift = marginFluidVal,
+ css = {};
+
+ if( "-=" == that.operator )
+ shift = Math.abs( tabsWidth - fixed.width() ) - marginFluidVal;
+
+ if( ! shift ) return;
+
+ css[marginFluid] = that.operator + shift + 'px';
+ fluid.animate( css, shift * msPerPx, "linear" );
+ }).mouseup(function(){
+ var tab, next;
+ fluid.stop(true);
+ tab = tabs[that.last]();
+ while( (next = tab[that.next]()) && next.length && ! next.isTabVisible() ) {
+ tab = next;
+ }
+ tab.makeTabVisible();
+ });
+ });
+ }
+
+ // TODO: fix this
+ function parseIntOrZero(str) {
+ var parsed = parseInt( str );
+ if( isNaN(parsed) || !parsed ) parsed = 0;
+ return parsed;
+ }
+
+ $(document).ready(function() {
+ zoninator.init();
+ })
+})(jQuery, window);
+
+if(typeof(console) === 'undefined')
+ console = { log: function(){} }
145 readme.txt
@@ -0,0 +1,145 @@
+=== Zone Manager (Zoninator) ===
+Contributors: batmoo, automattic
+Tags: zones, post order, post list, posts, order, zonination, content curation, curation, content management
+Requires at least: 3.4
+Tested up to: 3.4.1
+Stable tag: 0.4
+License: GPLv2
+
+Curation made easy! Create "zones" then add and order your content!
+
+== Description ==
+
+This plugin is designed to help you curate your content.
+
+Assign and order stories within zones that you create, edit, and delete. Then use the handy API functions to retrieve and display your content in your theme. Or for those who are a bit code-averse, try the handy widget.
+
+Key features included in the plugin:
+
+* Add/edit/delete zones
+* Add/remove posts (or any custom post type) to/from zones
+* Order posts in any given zone
+* Limit capabilities on who can add/edit/delete zones vs add content to zones
+* Locking mechanism, so only one user can edit a zone at a time (to avoid conflicts)
+* Idle control, so people can't keep the zoninator locked
+
+This plugin was built by [Mohammad Jangda](http://digitalize.ca) in conjunction with [William Davis](http://wpdavis.com/) and the [Bangor Daily News](http://www.bangordailynews.com/).
+
+== Installation ==
+
+1. Unzip contents and upload to the `/wp-content/plugins/` directory
+1. Activate the plugin through the 'Plugins' menu in WordPress
+1. Go to Dashboard > Zones to create and manage zones.
+1. Use the plugin's handy API functions to add zones to your theme.
+1. Enjoy!
+
+== Frequently Asked Questions ==
+
+= How do I disable the locking feature? =
+
+You can use a filter:
+
+`add_filter( 'zoninator_zone_max_lock_period', 'z_disable_zoninator_locks' );`
+
+= How do I change the the locking feature settings? =
+
+Filter the following and change according to your needs:
+
+* Number of seconds a lock is valid for, default `30`: `zoninator_zone_lock_period`
+* Max idle time in seconds: `zoninator_zone_max_lock_period`
+
+
+== Screenshots ==
+
+1. Create and manage your zones and content through a fairly intuitive and familiar interface
+
+== Changelog ==
+
+= 0.4 =
+
+* New dropdown that recent posts which can be adding to zones, props metromatic and Metro UK
+* New filter: zoninator_posts_per_page -- to override the default posts_per_page setting
+* Use core bundled versions of jQuery UI
+
+= 0.3 =
+
+* Introduce z_get_zone_query: returns a WP_Query object so you can run the loop like usual.
+* Disable editing and prefixing of slugs. They're just problems waiting to happen...
+* Add new filter to allow filtering of search args, props imrannathani for the suggestion
+* Allow scheduled posts to be added to zones so they automagically show up when they're published, props imrannathani for the idea.
+* Default to published post in all zone queries in the front-end. Scheduled posts can still be added via a filter.
+* Run clean_term_cache when a post is added or deleted from a zone so that the necessary caches are flushed.
+* Add new filter to limit editing access on a per-zone level. props hooman and the National Post team
+* Allow editor role (editor_others_posts) to manage zones (plus other capability fixes, props rinat k.)
+
+= 0.2 =
+
+* Move Zones to a top-level menu so that it's easier to access. And doesn't make much sense hidden under Dashboard.
+* Change the way error and success messages are handled.
+* jQuery 1.6.1 compatibility.
+* Bug fix: Custom Post Types not being included in search. Thanks Shawn!
+* Bug fix: Custom Post Types not being included in post list. Thanks Daniel!
+* Bug fix: Error thrown when removing last post in a zone. Thanks Daniel!
+* Other cleanup.
+
+= 0.1 =
+
+* Initial Release!
+
+== Upgrade Notice ==
+
+= 0.3 =
+
+* Slugs can no longer be edited. This is possibly a breaking change if you're using slugs to get zones or zone posts.
+
+= 0.2 =
+
+* Bunch of bug fixes and code improvements
+
+== Usage Notes ==
+
+= Example =
+
+You can work with with a zone's posts either as an array or a WP_Query object.
+
+<strong>WP_Query</strong>
+
+`
+$zone_query = z_get_zone_query( 'homepage' );
+if ( $zone_query->have_posts() ) :
+ while ( $zone_query->have_posts() ) $zone_query->the_post();
+ echo '<li>' . get_the_title() . </li>;
+ endwhile;
+endif;
+wp_reset_query();
+`
+
+<strong>Posts Array</strong>
+
+`
+$zone_posts = z_get_posts_in_zone( 'homepage' );
+foreach ( $zone_posts as $zone_post ) :
+ echo '<li>' . get_the_title( $zone_post->ID ) . </li>;
+endforeach;
+`
+
+= Function Reference =
+
+Get an array of all zones:
+
+`z_get_zones()`
+
+Get a single zone. Accepts either ID or slug.
+
+`z_get_zone( $zone )`
+
+Get an array of ordered posts in a given zone. Accepts either ID or slug.
+
+`z_get_posts_in_zone( $zone )`
+
+Get a WP_Query object for a given zone. Accepts either ID or slug.
+
+`z_get_zone_query( $zone );
+
+
+More functions listed in `functions.php`
BIN screenshot-1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
130 widget.zone-posts.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Zone Posts widget class
+ */
+class Zoninator_ZonePosts_Widget extends WP_Widget {
+
+ function Zoninator_ZonePosts_Widget() {
+ $widget_ops = array( 'classname' => 'widget-zone-posts', 'description' => __( 'Use this widget to display a list of posts from any zone.', 'zoninator' ) );
+ $this->WP_Widget( 'widget-zone-posts', __( 'Zone Posts', 'zoninator' ), $widget_ops );
+ $this->alt_option_name = 'widget_zone_posts';
+
+ add_action( 'save_post', array( &$this, 'flush_widget_cache' ) );
+ add_action( 'deleted_post', array( &$this, 'flush_widget_cache' ) );
+ add_action( 'switch_theme', array( &$this, 'flush_widget_cache' ) );
+ }
+
+ function widget( $args, $instance ) {
+ $cache = wp_cache_get( 'widget-zone-posts', 'widget' );
+
+ if ( !is_array( $cache ) )
+ $cache = array();
+
+ if ( isset( $cache[$args['widget_id']] ) ) {
+ echo $cache[$args['widget_id']];
+ return;
+ }
+
+ ob_start();
+ extract( $args );
+
+ $zone_id = $instance['zone_id'] ? $instance['zone_id'] : 0;
+ $show_description = $instance['show_description'] ? 1 : 0;
+
+ if( ! $zone_id )
+ return;
+
+ $zone = z_get_zone( $zone_id );
+
+ if( ! $zone )
+ return;
+
+ $posts = z_get_posts_in_zone( $zone_id );
+
+ if( empty( $posts ) )
+ return;
+
+ ?>
+ <?php echo $before_widget; ?>
+
+ <?php echo $before_title . esc_html( $zone->name ) . $after_title; ?>
+
+ <?php if( ! empty( $zone->description ) && $show_description ) : ?>
+ <p class="description"><?php echo esc_html( $zone->description ); ?></p>
+ <?php endif; ?>
+
+ <ul>
+ <?php foreach( $posts as $post ) : ?>
+ <li>
+ <a href="<?php echo get_permalink( $post->ID ); ?>">
+ <?php echo esc_html( get_the_title( $post->ID ) ); ?>
+ </a>
+ </li>
+ <?php endforeach; ?>
+ </ul>
+
+ <?php echo $after_widget; ?>
+ <?php
+ $cache[$args['widget_id']] = ob_get_flush();
+ wp_cache_set( 'widget-zone-posts', $cache, 'widget' );
+ }
+
+ function update( $new_instance, $old_instance ) {
+ $instance = $old_instance;
+ $new_instance = wp_parse_args( (array) $new_instance, array( 'zone_id' => 0, 'show_description' => 0 ) );
+
+ $instance['zone_id'] = absint( $new_instance['zone_id'] );
+ $instance['show_description'] = $new_instance['show_description'] ? 1 : 0;
+
+ $this->flush_widget_cache();
+
+ $alloptions = wp_cache_get( 'alloptions', 'options' );
+ if ( isset($alloptions['widget-zone-posts']) )
+ delete_option( 'widget-zone-posts' );
+
+ return $instance;
+ }
+
+ function flush_widget_cache() {
+ wp_cache_delete( 'widget-zone-posts', 'widget' );
+ }
+
+ function form( $instance ) {
+ // select - zone
+ // checkbox - show description
+
+ $zones = z_get_zones();
+
+ if( empty( $zones ) ) {
+ _e( 'You need to create at least one zone before you use this widget!', 'zoninator' );
+ return;
+ }
+
+ $zone_id = isset( $instance['zone_id'] ) ? absint( $instance['zone_id'] ) : 0;
+ $show_description = isset( $instance['show_description'] ) ? (bool)$instance['show_description'] : true;
+ ?>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'zone_id' ); ?>"><?php _e('Zone:'); ?></label>
+ <select class="widefat" id="<?php echo $this->get_field_id( 'zone_id' ); ?>" name="<?php echo $this->get_field_name( 'zone_id' ); ?>">
+ <option value="0" <?php selected( $zone_id, 0 ); ?>>
+ <?php _e( '-- Select a zone --', 'zoninator' ); ?>
+ </option>
+
+ <?php foreach( $zones as $zone ) : ?>
+ <option value="<?php echo $zone->term_id; ?>" <?php selected( $zone_id, $zone->term_id ); ?>>
+ <?php echo esc_html( $zone->name ); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'show_description' ); ?>">
+ <input id="<?php echo $this->get_field_id( 'show_description' ); ?>" name="<?php echo $this->get_field_name( 'show_description' ); ?>" <?php checked( true, $show_description ); ?> type="checkbox" value="1" />
+ <?php _e( 'Show zone description in widget', 'zoninator' ); ?>
+ </label>
+ </p>
+ <?php
+ }
+}
1,288 zoninator.php
@@ -0,0 +1,1288 @@
+<?php
+/*
+Plugin Name: Zone Manager (Zoninator)
+Description: Curation made easy! Create "zones" then add and order your content!
+Author: Mohammad Jangda, Automattic
+Version: 0.4
+Author URI: http://vip.wordpress.com
+
+Copyright 2010-2012 Mohammad Jangda, Automattic
+
+This plugin was built by Mohammad Jangda in conjunction with William Davis and the Bangor Daily News.
+
+GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+if( ! class_exists( 'Zoninator' ) ) :
+
+define( 'ZONINATOR_VERSION', '0.4' );
+define( 'ZONINATOR_PATH', dirname( __FILE__ ) );
+define( 'ZONINATOR_URL', trailingslashit( plugins_url( '', __FILE__ ) ) );
+
+require_once( ZONINATOR_PATH . '/functions.php' );
+require_once( ZONINATOR_PATH . '/widget.zone-posts.php');
+
+class Zoninator
+{
+ var $key = 'zoninator';
+ var $zone_taxonomy = 'zoninator_zones';
+ var $zone_term_prefix = 'zone-';
+ var $zone_meta_prefix = '_zoninator_order_';
+ var $zone_nonce_prefix = 'zone-nonce';
+ var $zone_ajax_nonce_action = 'ajax-action';
+ var $zone_lock_period = 30; // number of seconds a lock is valid for
+ var $zone_max_lock_period = 600; // max number of seconds for all locks in a session
+ var $post_types = null;
+ var $zone_detail_defaults = array(
+ 'description' => ''
+ // Add additional properties here!
+ );
+ var $zone_messages = null;
+ var $posts_per_page = 10;
+
+ function __construct() {
+ add_action( 'init', array( $this, 'init' ) );
+
+ add_action( 'widgets_init', array( $this, 'widgets_init' ) );
+
+ $this->zone_messages = array(
+ 'insert-success' => __( 'The zone was successfully created.', 'zoninator' ),
+ 'update-success' => __( 'The zone was successfully updated.', 'zoninator' ),
+ 'delete-success' => __( 'The zone was successfully deleted.', 'zoninator' ),
+ 'error-general' => __( 'Sorry, something went wrong! Please try again?', 'zoninator' ),
+ 'error-zone-lock' => __( 'Sorry, this zone is in use by %s and is currently locked. Please try again later.', 'zoninator' ),
+ 'error-zone-lock-max' => __( 'Sorry, you have reached the maximum idle limit and will now be redirected to the Dashboard.', 'zoninator' ),
+ );
+
+ $this->default_post_types = array( 'post' );
+
+ $this->zone_lock_period = apply_filters( 'zoninator_zone_lock_period', $this->zone_lock_period );
+ $this->zone_max_lock_period = apply_filters( 'zoninator_zone_max_lock_period', $this->zone_max_lock_period );
+ $this->posts_per_page = apply_filters( 'zoninator_posts_per_page', $this->posts_per_page );
+ }
+
+ function init() {
+
+ do_action( 'zoninator_pre_init' );
+
+ // Default post type support
+ foreach( $this->default_post_types as $post_type )
+ add_post_type_support( $post_type, $this->zone_taxonomy );
+
+ // Register taxonomy
+ if( ! taxonomy_exists( $this->zone_taxonomy ) ) {
+ register_taxonomy( $this->zone_taxonomy, $this->get_supported_post_types(), array(
+ 'label' => __( 'Zones', 'zoninator' ),
+ 'hierarchical' => false,
+ 'query_var' => false,
+ 'rewrite' => false,
+ 'public' => false,
+
+ ) );
+ }
+
+ add_action( 'admin_init', array( $this, 'admin_controller' ) );
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
+
+ add_action( 'admin_menu', array( $this, 'admin_page_init' ) );
+
+ do_action( 'zoninator_post_init' );
+ }
+
+ function widgets_init() {
+ register_widget( 'Zoninator_ZonePosts_Widget' );
+ }
+
+ // Add necessary AJAX actions
+ function admin_ajax_init( ) {
+ add_action( 'wp_ajax_zoninator_reorder_posts', array( $this, 'ajax_reorder_posts' ) );
+ add_action( 'wp_ajax_zoninator_add_post', array( $this, 'ajax_add_post' ) );
+ add_action( 'wp_ajax_zoninator_remove_post', array( $this, 'ajax_remove_post' ) );
+ add_action( 'wp_ajax_zoninator_search_posts', array( $this, 'ajax_search_posts' ) );
+ add_action( 'wp_ajax_zoninator_update_lock', array( $this, 'ajax_update_lock' ) );
+ }
+
+ function admin_init() {
+
+ $this->admin_ajax_init();
+
+ // Enqueue Scripts and Styles
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_styles' ) );
+ }
+
+ function admin_page_init() {
+ // Set up page
+ add_menu_page( __( 'Zoninator', 'zoninator' ), __( 'Zones', 'zoninator' ), $this->_get_manage_zones_cap(), $this->key, array( $this, 'admin_page' ), '', 11 );
+ }
+
+ function admin_enqueue_scripts() {
+ if( $this->is_zoninator_page() ) {
+ wp_enqueue_script( 'zoninator-js', ZONINATOR_URL . 'js/zoninator.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-mouse', 'jquery-ui-position', 'jquery-ui-sortable', 'jquery-ui-autocomplete' ), ZONINATOR_VERSION, true );
+
+ $options = array(
+ 'baseUrl' => $this->_get_zone_page_url(),
+ 'adminUrl' => admin_url(),
+ 'ajaxNonceAction' => $this->_get_nonce_key( $this->zone_ajax_nonce_action ),
+ 'errorGeneral' => $this->_get_message( 'error-general' ),
+ 'errorZoneLock' => sprintf( $this->_get_message( 'error-zone-lock' ), __( 'another user', 'zoninator' ) ),
+ 'errorZoneLockMax' => $this->_get_message( 'error-zone-lock-max' ),
+ 'zoneLockPeriod' => $this->zone_lock_period,
+ 'zoneLockPeriodMax' => $this->zone_max_lock_period,
+ );
+ wp_localize_script( 'zoninator-js', 'zoninatorOptions', $options );
+
+ }
+ }
+
+ function admin_enqueue_styles() {
+ if( $this->is_zoninator_page() ) {
+ wp_enqueue_style( 'zoninator-jquery-ui', ZONINATOR_URL . 'css/jquery-ui/smoothness/jquery-ui-zoninator.css', false, ZONINATOR_VERSION, 'all' );
+ wp_enqueue_style( 'zoninator-styles', ZONINATOR_URL . 'css/zoninator.css', false, ZONINATOR_VERSION, 'all' );
+ }
+ }
+
+ function admin_controller() {
+ if( $this->is_zoninator_page() ) {
+ $action = $this->_get_request_var( 'action' );
+
+ switch( $action ) {
+
+ case 'insert':
+ case 'update':
+ $zone_id = $this->_get_post_var( 'zone_id', 0, 'absint' );
+
+ $this->verify_nonce( $action );
+ $this->verify_access( $action, $zone_id );
+
+ $name = $this->_get_post_var( 'name' );
+ $slug = $this->_get_post_var( 'slug', sanitize_title( $name ) );
+ $details = array(
+ 'description' => $this->_get_post_var( 'description', '', 'strip_tags' )
+ );
+
+ // TODO: handle additional properties
+ if( $zone_id ) {
+ $result = $this->update_zone( $zone_id, array(
+ 'name' => $name,
+ 'slug' => $slug,
+ 'details' => $details
+ ) );
+
+ } else {
+ $result = $this->insert_zone( $slug, $name, $details );
+ }
+
+ if( is_wp_error( $result ) ) {
+ wp_redirect( add_query_arg( 'message', 'error-general' ) );
+ exit;
+ } else {
+ if( ! $zone_id && isset( $result['term_id'] ) )
+ $zone_id = $result['term_id'];
+
+ // Redirect with success message
+ $message = sprintf( '%s-success', $action );
+ wp_redirect( $this->_get_zone_page_url( array( 'action' => 'edit', 'zone_id' => $zone_id, 'message' => $message ) ) );
+ exit;
+ }
+ break;
+
+ case 'delete':
+ $zone_id = $this->_get_request_var( 'zone_id', 0, 'absint' );
+
+ $this->verify_nonce( $action );
+ $this->verify_access( $action, $zone_id );
+
+ if( $zone_id ) {
+ $result = $this->delete_zone( $zone_id );
+ }
+
+ if( is_wp_error( $result ) ) {
+ $redirect_args = array( 'error' => $result->get_error_messages() );
+ } else {
+ $redirect_args = array( 'message' => 'delete-success' );
+ }
+
+ wp_redirect( $this->_get_zone_page_url( $redirect_args ) );
+ exit;
+ }
+ }
+ }
+
+ function admin_page() {
+ global $zoninator_admin_page;
+
+ $view = $this->_get_value_or_default( 'view', $zoninator_admin_page, 'edit.php' );
+ $view = sprintf( '%s/views/%s', ZONINATOR_PATH, $view );
+ $title = $this->_get_value_or_default( 'title', $zoninator_admin_page, __( 'Zones', 'zoninator' ) );
+
+ $zones = $this->get_zones();
+
+ $default_active_zone = 0;
+ if( ! $this->_current_user_can_add_zones() ) {
+ if( ! empty( $zones ) )
+ $default_active_zone = $zones[0]->term_id;
+ }
+
+ $active_zone_id = $this->_get_request_var( 'zone_id', $default_active_zone, 'absint' );
+ $active_zone = ! empty( $active_zone_id ) ? $this->get_zone( $active_zone_id ) : array();
+
+ $message = $this->_get_message( $this->_get_get_var( 'message', '', 'urldecode' ) );
+ $error = $this->_get_get_var( 'error', '', 'urldecode' );
+
+ ?>
+ <div class="wrap zoninator-page">
+ <div id="icon-edit-pages" class="icon32"><br /></div>
+ <h2><?php echo esc_html( $title ); ?></h2>
+
+ <?php if( $message ) : ?>
+ <div id="zone-message" class="updated below-h2">
+ <p><?php echo esc_html( $message ); ?></p>
+ </div>
+ <?php endif; ?>
+ <?php if( $error ) : ?>
+ <div id="zone-message" class="error below-h2">
+ <p><?php echo esc_html( $error ); ?></p>
+ </div>
+ <?php endif; ?>
+
+ <div id="zoninator-wrap">
+
+ <?php $this->admin_page_zone_tabs( $zones, $active_zone_id ); ?>
+
+ <?php $this->admin_page_zone_edit( $active_zone ); ?>
+
+ </div>
+ </div>
+ <?php
+ }
+
+ function admin_page_zone_tabs( $zones, $active_zone_id = 0 ) {
+ $new_link = $this->_get_zone_page_url( array( 'action' => 'new' ) );
+ ?>
+ <div class="nav-tabs-container zone-tabs-container">
+ <div class="nav-tabs-nav-wrapper zone-tabs-nav-wrapper">
+ <div class="nav-tabs-wrapper zone-tabs-wrapper">
+ <div class="nav-tabs zone-tabs">
+ <?php foreach( $zones as $zone ) : ?>
+ <?php $zone_id = $this->get_zone_id( $zone ); ?>
+ <?php $zone_link = $this->_get_zone_page_url( array( 'action' => 'edit', 'zone_id' => $zone_id ) ); ?>
+
+ <?php if( $active_zone_id && $zone_id == $active_zone_id ) : ?>
+ <span class="nav-tab nav-tab-active zone-tab zone-tab-active"><?php echo esc_html( $zone->name ); ?></span>
+ <?php else : ?>
+ <a href="<?php echo esc_url( $zone_link ); ?>" class="nav-tab zone-tab"><?php echo esc_html( $zone->name ); ?></a>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ </div>
+ </div>
+ </div>
+
+ <div class="zone-tab-new">
+ <?php if( $this->_current_user_can_add_zones() ) : ?>
+ <?php if( $active_zone_id ) : ?>
+ <a href="<?php echo $new_link; ?>" class="nav-tab zone-tab"><?php _e( '+', 'zoninator' ); ?></a>
+ <?php else : ?>
+ <span class="nav-tab nav-tab-active zone-tab zone-tab-active"><?php _e( '+', 'zoninator' ); ?></span>
+ <?php endif; ?>
+ <?php endif; ?>
+ </div>
+ <div class="clear"></div>
+ </div>
+ <?php
+ }
+
+ function admin_page_zone_edit( $zone = null ) {
+ $zone_id = $this->_get_value_or_default( 'term_id', $zone, 0, 'absint' );
+ $zone_name = $this->_get_value_or_default( 'name', $zone );
+ $zone_slug = $this->_get_value_or_default( 'slug', $zone, '', array( $this, 'get_unformatted_zone_slug' ) );
+ $zone_description = $this->_get_value_or_default( 'description', $zone );
+
+ $zone_posts = $zone_id ? $this->get_zone_posts( $zone ) : array();
+
+ $zone_locked = $this->is_zone_locked( $zone_id );
+
+ $delete_link = $this->_get_zone_page_url( array( 'action' => 'delete', 'zone_id' => $zone_id ) );
+ $delete_link = wp_nonce_url( $delete_link, $this->_get_nonce_key( 'delete' ) );
+ ?>
+ <div id="zone-edit-wrapper">
+ <?php if( ( $zone_id == 0 && $this->_current_user_can_add_zones() ) || ( $zone_id != 0 && $this->_current_user_can_manage_zones() ) ) : ?>
+ <?php if( $zone_locked ) : ?>
+ <?php $locking_user = get_userdata( $zone_locked ); ?>
+ <div class="updated below-h2">
+ <p><?php echo sprintf( $this->_get_message( 'error-zone-lock' ), sprintf( '<a href="mailto:%s">%s</a>', $locking_user->user_email, $locking_user->display_name ) ); ?></p>
+ </div>
+ <input type="hidden" id="zone-locked" name="zone-locked" value="1" />
+ <?php endif; ?>
+ <div class="col-wrap zone-col zone-info-col">
+ <div class="form-wrap zone-form zone-info-form">
+
+ <?php if( $this->_current_user_can_edit_zones( $zone_id ) && ! $zone_locked ) : ?>
+
+ <form id="zone-info" method="post">
+
+ <?php do_action( 'zoninator_pre_zone_fields', $zone ); ?>
+
+ <div class="form-field zone-field">
+ <label for="zone-name"><?php _e( 'Name', 'zoninator' ); ?></label>
+ <input type="text" id="zone-name" name="name" value="<?php echo esc_attr( $zone_name ); ?>" />
+ </div>
+
+ <?php if( $zone_id ) : ?>
+ <div class="form-field zone-field">
+ <label for="zone-slug"><?php _e( 'Slug', 'zoninator' ); ?></label>
+ <span><?php echo esc_attr( $zone_slug ); ?></span>
+ <input type="hidden" id="zone-slug" name="slug" value="<?php echo esc_attr( $zone_slug ); ?>" />
+ </div>
+ <?php endif; ?>
+
+ <div class="form-field zone-field">
+ <label for="zone-description"><?php _e( 'Description', 'zoninator' ); ?></label>
+ <textarea id="zone-description" name="description"><?php echo esc_html( $zone_description ); ?></textarea>
+ </div>
+
+ <?php do_action( 'zoninator_post_zone_fields', $zone ); ?>
+
+ <?php if( $zone_id ) : ?>
+ <input type="hidden" name="zone_id" id="zone_id" value="<?php echo esc_attr( $zone_id ) ?>" />
+ <?php wp_nonce_field( $this->_get_nonce_key( 'update' ) ); ?>
+ <?php else : ?>
+ <?php wp_nonce_field( $this->_get_nonce_key( 'insert' ) ); ?>
+ <?php endif; ?>
+
+ <div class="submit-field submitbox">
+ <input type="submit" value="<?php _e('Save', 'zoninator'); ?>" name="submit" class="button-primary" />
+
+ <?php if( $zone_id ) : ?>
+ <a href="<?php echo $delete_link ?>" class="submitdelete" onclick="return confirm('<?php echo esc_js( 'Are you sure you want to delete this zone?', 'zoninator' ); ?>')"><?php _e('Delete', 'zoninator') ?></a>
+ <?php endif; ?>
+ </div>
+
+ <input type="hidden" name="action" value="<?php echo $zone_id ? 'update' : 'insert'; ?>">
+ <input type="hidden" name="page" value="<?php echo $this->key; ?>">
+
+ </form>
+ <?php else : ?>
+ <div id="zone-info-readonly" class="readonly">
+ <?php do_action( 'zoninator_pre_zone_readonly', $zone ); ?>
+
+ <div class="form-field zone-field">
+ <label for="zone-name"><?php _e( 'Name', 'zoninator' ); ?></label>
+ <span><?php echo esc_attr( $zone_name ); ?></span>
+ </div>
+
+ <!--
+ <div class="form-field zone-field">
+ <label for="zone-slug"><?php _e( 'Slug', 'zoninator' ); ?></label>
+ <span><?php echo esc_attr( $zone_slug ); ?></span>
+ </div>
+ -->
+
+ <div class="form-field zone-field">
+ <label for="zone-description"><?php _e( 'Description', 'zoninator' ); ?></label>
+ <span><?php echo esc_html( $zone_description ); ?></span>
+ </div>
+
+ <input type="hidden" name="zone_id" id="zone_id" value="<?php echo esc_attr( $zone_id ) ?>" />
+
+ <?php do_action( 'zoninator_post_zone_readonly', $zone ); ?>
+ </div>
+ <?php endif; ?>
+
+ <?php // Ideally, we should seperate nonces for each action. But this will do for simplicity. ?>
+ <?php wp_nonce_field( $this->_get_nonce_key( $this->zone_ajax_nonce_action ), $this->_get_nonce_key( $this->zone_ajax_nonce_action ), false ); ?>
+ </div>
+
+ </div>
+
+ <div class="col-wrap zone-col zone-posts-col">
+ <div class="zone-posts-wrapper <?php echo ! $this->_current_user_can_manage_zones( $zone_id ) || $zone_locked ? 'readonly' : ''; ?>">
+ <?php if( $zone_id ) : ?>
+ <h3><?php _e( 'Zone Content', 'zoninator' ); ?></h3>
+
+ <?php $this->zone_admin_recent_posts_dropdown( $zone_id ); ?>
+
+ <?php $this->zone_admin_search_form(); ?>
+
+ <div class="zone-posts-list">
+ <?php foreach( $zone_posts as $post ) : ?>
+ <?php $this->admin_page_zone_post( $post, $zone ); ?>
+ <?php endforeach; ?>
+ </div>
+
+ <?php else : ?>
+ <p class="description"><?php _e( 'To create a zone, enter a name (and any other info) to to left and click "Save". You can then choose content items to add to the zone.', 'zoninator' ); ?></p>
+ <?php endif; ?>
+ </div>
+ </div>
+ <?php endif; ?>
+ </div>
+
+ <?php
+ }
+
+ function admin_page_zone_post( $post, $zone ) {
+ $columns = apply_filters( 'zoninator_zone_post_columns', array(
+ 'position' => array( $this, 'admin_page_zone_post_col_position' ),
+ 'info' => array( $this, 'admin_page_zone_post_col_info' )
+ ), $post, $zone );
+ ?>
+ <div id="zone-post-<?php echo $post->ID; ?>" class="zone-post" data-post-id="<?php echo $post->ID; ?>">
+ <table>
+ <tr>
+ <?php foreach( $columns as $column_key => $column_callback ) : ?>
+ <?php if( is_callable( $column_callback ) ) : ?>
+ <td class="zone-post-col zone-post-<?php echo $column_key; ?>">
+ <?php call_user_func( $column_callback, $post, $zone ); ?>
+ </td>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ </tr>
+ </table>
+ <input type="hidden" name="zone-post-id" value="<?php echo $post->ID; ?>" />
+ </div>
+ <?php
+ }
+
+ function admin_page_zone_post_col_position( $post, $zone ) {
+ $current_position = $this->get_post_order( $post->ID, $zone );
+ ?>
+ <span title="<?php esc_attr_e( 'Click and drag to change the position of this item.', 'zoninator' ); ?>">
+ <?php echo esc_html( $current_position ); ?>
+ </span>
+ <?php
+ }
+ function admin_page_zone_post_col_info( $post, $zone ) {
+ $action_links = array(
+ sprintf( '<a href="%s" class="edit" target="_blank" title="%s">%s</a>', get_edit_post_link( $post->ID ), __( 'Opens in new window', 'zoninator' ), __( 'Edit', 'zoninator' ) ),
+ sprintf( '<a href="#" class="delete" title="%s">%s</a>', __( 'Remove this item from the zone', 'zoninator' ), __( 'Remove', 'zoninator' ) ),
+ sprintf( '<a href="%s" class="view" target="_blank" title="%s">%s</a>', get_permalink( $post->ID ), __( 'Opens in new window', 'zoninator' ), __( 'View', 'zoninator' ) ),
+ // Move To
+ // Copy To
+ );
+ ?>