summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Robbins2007-11-23 17:04:33 +0000
committerJeff Robbins2007-11-23 17:04:33 +0000
commit3efc2536065b5dd7db27e144a8bc10d8f20697be (patch)
tree436f46daf11bd95e9b5ebd3c5c6cea6802f462c3
parent5bfb1a8681f792e830fd3592405bf354d1091ba6 (diff)
themer popup stuff with overhaul of devel_print_object()
-rw-r--r--devel.css8
-rw-r--r--devel.module134
-rw-r--r--devel_themer.css100
-rw-r--r--devel_themer.js162
-rw-r--r--devel_themer.module90
-rw-r--r--jquery-ui-drag.min.js44
6 files changed, 490 insertions, 48 deletions
diff --git a/devel.css b/devel.css
index ec011c1..0199d03 100644
--- a/devel.css
+++ b/devel.css
@@ -1,3 +1,11 @@
.dev-query, .dev-timer, .dev-memory-usage {
padding-top: 2em;
+}
+
+.devel-obj-output .field {
+ color: red;
+}
+
+.devel-obj-output dd {
+ display: block;
} \ No newline at end of file
diff --git a/devel.module b/devel.module
index dfe46d7..44a4eb0 100644
--- a/devel.module
+++ b/devel.module
@@ -135,7 +135,7 @@ function devel_menu() {
$items['node/%node/load'] = array(
'title' => 'Dev load',
'page callback' => 'devel_load_object',
- 'page arguments' => array(1),
+ 'page arguments' => array(1, 'node'),
'access callback' => 'user_access',
'access arguments' => array('access devel information'),
'type' => MENU_LOCAL_TASK,
@@ -151,7 +151,7 @@ function devel_menu() {
$items['user/%user/load'] = array(
'title' => 'Devel load',
'page callback' => 'devel_load_object',
- 'page arguments' => array(1),
+ 'page arguments' => array(1, 'user'),
'access callback' => 'user_access',
'access arguments' => array('access devel information'),
'type' => MENU_LOCAL_TASK,
@@ -308,13 +308,13 @@ function devel_block_devel() {
$links[] = l(t('Devel settings'), 'admin/settings/devel', array('attributes' => array('title' => t('Adjust module settings for devel module.'))));
$links[] = l(t('Empty cache'), 'devel/cache/clear', array('attributes' => array('title' => t('Clear the CSS cache and all database cache tables which store page, node, theme and variable caches.')), 'query' => drupal_get_destination()));
$links[] = l(t('PHPinfo()'), 'devel/phpinfo', array('attributes' => array('title' => t('Display information about your PHP installation.'))));
-
+
$mini[] = l(t('func'), 'devel/reference', array('attributes' => array('title' => t('View a list of currently defined user functions with documentation links.'))));
$mini[] = l(t('theme'), 'devel/theme/registry', array('attributes' => array('title' => t('View a list of available theme functions acros the whole site.'))));
$mini[] = l(t('elements'), 'devel/elements', array('attributes' => array('title' => t('View the active form/render elements for this site.'))));
$mini[] = l(t('sess'), 'devel/session', array('attributes' => array('title' => t('List the contents of $_SESSION.'))));
$links[] = implode('  ', $mini);
-
+
$links[] = l(t('Reinstall modules'), 'devel/reinstall', array('attributes' => array('title' => t('Re-run hook_install() for a given module.')), 'query' => drupal_get_destination()));
$links[] = l(t('Rebuild menus'), 'devel/menu/reset', array('attributes' => array('title' => t('Rebuild menu based on hook_menu() and any custom changes all menu items to their default settings.')), 'query' => drupal_get_destination()));
$links[] = l(t('Variable editor'), 'devel/variable', array('attributes' => array('title' => t('Edit and delete site variables.'))));
@@ -505,7 +505,7 @@ function devel_shutdown() {
if (!variable_get('devel_query_display', 0) && variable_get('dev_timer', 0)) {
$output .= '<div class="dev-timer">'. devel_timer() .' '. $query_summary. '</div>';
}
-
+
// Query log on.
$sum = 0;
if (variable_get('devel_query_display', FALSE)) {
@@ -538,7 +538,7 @@ function devel_shutdown() {
}
// TODO: gzip this text if we are sending a gzip page. see drupal_page_header().
}
-
+
if ($output) {
print $output;
}
@@ -997,10 +997,10 @@ function devel_switch_user($name = NULL) {
/**
* Menu callback; prints the loaded structure of the current node/user.
*/
-function devel_load_object($object) {
+function devel_load_object($object, $name = NULL) {
$title = isset($object->title) ? $object->title : $object->name;
drupal_set_title(check_plain($title));
- return kdevel_print_object($object);
+ return kdevel_print_object($object, '$'. $name .'->');
}
/**
@@ -1013,15 +1013,23 @@ function devel_render_object($type, $object) {
drupal_set_title(check_plain($title));
$function = $type. '_build_content';
$content = $function($object, FALSE, FALSE);
- return kdevel_print_object($content);
+ return kdevel_print_object($content, '$'. $type .'->');
}
function devel_elements_page() {
return kdevel_print_object(module_invoke_all('elements'));
}
-function kdevel_print_object($object) {
- return has_krumo() ? krumo_ob($object) : devel_print_object($object);
+/**
+ * Print an object or array using either Krumo (if installed) or devel_print_object()
+ *
+ * @param $object
+ * array or object to print
+ * @param $prefix
+ * prefixing for output items
+ */
+function kdevel_print_object($object, $prefix = NULL) {
+ return has_krumo() ? krumo_ob($object) : devel_print_object($object, $prefix);
}
// Save krumo htlm using output buffering.
@@ -1033,23 +1041,93 @@ function krumo_ob($object) {
return $output;
}
-function devel_print_object($object) {
- $output = '';
- foreach ($object as $field => $value) {
- if (is_null($value)) {
- $printed_value = 'NULL';
- }
- else if (is_array($value) || is_object($value)) {
- ob_start();
- print_r($value);
- $printed_value = ob_get_clean();
- $printed_value = '<pre>'. check_plain($printed_value) .'</pre>';
- }
- else {
- $printed_value = check_plain($value);
- }
+/**
+ * Display an object or array
+ *
+ * @param $object
+ * the object or array
+ * @param $prefix
+ * prefix for the output items (example "$node->", "$user->", "$")
+ * @param $header
+ * set to FALSE to suppress the output of the h3
+ */
+function devel_print_object($object, $prefix = NULL, $header = TRUE) {
+ drupal_add_css(drupal_get_path('module', 'devel'). '/devel.css');
+ $output = '<div class="devel-obj-output">';
+ if ($header) {
+ $output .= '<h3>'. t('Display of !type !obj', array('!type' => str_replace(array('$', '->'), '', $prefix), '!obj' => gettype($object))). '</h3>';
+ }
+ $output .= _devel_print_object($object, $prefix);
+ $output .= '</div>';
+ return $output;
+}
- $output .= theme('box', $field, $printed_value);
+/**
+ * Recursive (and therefore magical) function goes through an array or object and
+ * returns a nicely formatted listing of its contents.
+ *
+ * @param $obj
+ * array or object to recurse through
+ * @param $prefix
+ * prefix for the output items (example "$node->", "$user->", "$")
+ * @param $parents
+ * used by recursion
+ * @param $object
+ * used by recursion
+ * @return
+ * fomatted html
+ *
+ * @todo
+ * currently there are problems sending an array with a varname
+ */
+function _devel_print_object($obj, $prefix = NULL, $parents = FALSE, $object = FALSE) {
+
+ static $root_type, $out_format;
+ if (!isset($root_type)) {
+ $root_type = gettype($obj);
+ }
+
+ if (is_object($obj)) {
+ $obj = (array)$obj;
+ }
+ if (is_array($obj)) {
+ $output .= "<dl>\n";
+ foreach($obj as $field => $value) {
+ if ($parents) {
+ if ($object) {
+ $field = $parents .'->'. $field;
+ }
+ else {
+ if (is_int($field)) {
+ $field = $parents .'['. $field .']';
+ }
+ else {
+ $field = $parents .'[\''. $field .'\']';
+ }
+ }
+ }
+
+ $type = "";
+ if (!is_string($value)) {
+ $type = " (". gettype($value) .")";
+ }
+
+ $output .= '<span class="devel-attr">';
+ $output .= "<dt><span class=\"field\">{$prefix}{$field}</span>$type</dt>\n";
+ $output .= "<dd>\n";
+ if (is_array($value)) {
+ $output .= _devel_print_object($value, $prefix, $field);
+ }
+ elseif (is_object($value)) {
+ $output .= _devel_print_object((array)$value, $prefix, $field, TRUE);
+ }
+ else {
+ $value = is_bool($value) ? ($value ? 'TRUE' : 'FALSE') : $value;
+ $output .= htmlspecialchars(print_r($value, TRUE)) ."\n";
+ }
+ $output .= "</dd></span>\n";
+ }
+ $output .= "</dl>\n";
}
return $output;
}
@@ -1209,7 +1287,7 @@ function dprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r')
}
/**
- *
+ *
*/
function dkr($input, $return = FALSE, $name = NULL) {
require_once './'. drupal_get_path('module', 'devel'). '/krumo/class.krumo.php';
diff --git a/devel_themer.css b/devel_themer.css
index a70f8ab..35a72ea 100644
--- a/devel_themer.css
+++ b/devel_themer.css
@@ -7,3 +7,103 @@
z-index: 10001;
color: #fff;
}
+
+#themer-popup {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
+ color: #FFFFFF;
+ background-color: #333;
+ width: 400px;
+ font-size: x-small;
+ opacity:.9;
+ filter: alpha(opacity=90);
+ border: 1px solid #000;
+ display: none;
+ z-index: 10001;
+}
+
+#themer-popup a, #themer-popup a:visited, #themer-popup span.parent {
+ color: #FFF;
+ text-decoration: none;
+ font-weight: normal;
+ margin-bottom: -4px;
+ border-bottom:1px dotted #666666;
+ cursor: pointer;
+}
+
+#themer-popup .topper {
+ text-align: center;
+ padding: 2px 5px;
+ background-color:#666;
+ cursor: move;
+}
+#themer-popup .close {
+ float: right;
+ cursor: pointer;
+}
+#themer-popup .starter {
+ font-size:2em;
+}
+
+#themer-popup #parents {
+ padding-top: 5px;
+ background-color: #222;
+ color: #999;
+ font-weight: bold;
+}
+#themer-popup .row {
+ padding: 0 5px 5px;
+ border-top: 1px solid #777;
+}
+#themer-popup dl {
+ margin: 0;
+}
+#themer-popup dt {
+ font-weight: bold;
+}
+#themer-popup dd {
+ margin: 0 0 0 15px;
+ display:block;
+}
+#themer-popup .devel-obj-output dt {
+ cursor: pointer;
+}
+
+#themer-popup .devel-obj-output .field {
+ color: #CCC;
+}
+
+#themer-popup .info .key {
+ font-size: 18px;
+ font-weight: bold;
+}
+#themer-popup .info dt {
+ color: #999;
+}
+
+#themer-popup h4 {
+ margin: 0;
+ font-size:x-small;
+ text-align: center;
+ font-weight:normal;
+ color: #999;
+}
+
+#themer-toggle {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ padding: 3px 5px;
+ background: #fff;
+ color: #008;
+ cursor: pointer;
+ z-index: 10002;
+ font-size: small;
+ background-color: #333;
+ opacity: .8;
+ color: #FFF;
+ border-top: 1px solid #000;
+ border-right: 1px solid #000;
+} \ No newline at end of file
diff --git a/devel_themer.js b/devel_themer.js
index 821e65b..4049daf 100644
--- a/devel_themer.js
+++ b/devel_themer.js
@@ -1,15 +1,161 @@
if (Drupal.jsEnabled) {
$(document).ready(function () {
-
+
//theme log
+ /*
$('span.thmr_call').each(function () {
- var text = $(this).attr('thmr_key');
- var enabled = 1;
- var label = $('<span style="display: none" class="field-label field-tip">'+ text +'</span>').prependTo(this);
-
- $(this)
- .mouseover(function () { if (enabled) { $(label).show(); } })
- .mouseout(function () { if (enabled) { $(label).hide(); } });
+ this.onclick = function () {
+ if (themerEnabled) {
+ id = $(this).attr('id');
+ console.log(id);
+ }
+ };
+ });
+ */
+
+ var themerEnabled = 0;
+ var themerToggle = function () {
+ themerEnabled = 1 - themerEnabled;
+ $('input', this).attr('checked', themerEnabled ? 'checked' : '');
+ $('#themer-popup').css('display', themerEnabled ? 'block' : 'none');
+ if (themerEnabled) {
+ document.onclick = themerEvent;
+ }
+ else {
+ document.onclick = null;
+ }
+ };
+ $(Drupal.settings.thmr_popup)
+ .appendTo($('body'));
+
+ $('<div id="themer-toggle"><input type="checkbox" />Themer Info</div>')
+ .appendTo($('body'))
+ .click(themerToggle);
+
+ $('#themer-popup').draggable({
+ opacity: .6,
+ handle: $('#themer-popup .topper')
+ });
+ // close box
+ $('#themer-popup .topper .close').click(function() {
+ themerToggle();
});
});
}
+
+function themerDoIt(obj) {
+ //console.log(obj);
+ if (thmrInPop(obj)) {
+ return true;
+ }
+ var objs = thmrFindParents(obj);
+ if (objs.length) {
+ thmrRebuildPopup(objs);
+ }
+ return false;
+}
+
+function thmrInPop(obj) {
+ //is the element in either the popup box or the toggle div?
+ if (obj.id == "themer-popup" || obj.id == "themer-toggle") return true;
+ if (obj.parentNode) {
+ while (obj = obj.parentNode) {
+ if (obj.id=="themer-popup" || obj.id == "themer-toggle") return true;
+ }
+ }
+ return false;
+}
+
+function themerEvent(e) {
+ if (!e) {
+ var e = window.event;
+ };
+ if (e.target) var tg = e.target;
+ else if (e.srcElement) var tg = e.srcElement;
+ return themerDoIt(tg);
+}
+
+/**
+ * Find all parents with class="thmr_call"
+ */
+function thmrFindParents(obj) {
+ var parents = new Array();
+ if (obj && obj.parentNode) {
+ while (obj = obj.parentNode) {
+ if (obj.className == 'thmr_call') {
+ parents[parents.length] = obj;
+ }
+ }
+ }
+ return parents;
+}
+
+function thmrRefreshCollapse() {
+ $('#themer-popup .devel-obj-output dt').each(function() {
+ $(this).toggle(function() {
+ $(this).parent().children('dd').show();
+ }, function() {
+ $(this).parent().children('dd').hide();
+ });
+ });
+ $('#themer-popup .devel-obj-output dd').hide();
+}
+
+function thmrRebuildPopup(objs) {
+ // rebuild the popup box
+ var id = objs[0].id;
+ var type = $(objs[0]).attr('thmr_type');
+ var key = $(objs[0]).attr('thmr_key');
+ var vars = Drupal.settings[id];
+ var strs = Drupal.settings.thmrStrings;
+ //console.log(vars);
+
+ $('#themer-popup div.starter').empty();
+
+ if (type == 'func') {
+ $('#themer-popup dd.key').empty().prepend('<a href="'+ strs.api_site +'api/search/'+ strs.drupal_version +'/'+ key +'" title="'+ strs.drupal_api_docs +'">'+ key +'()</a>');
+ $('#themer-popup dt.key-type').empty().prepend(strs.function_called);
+ }
+ else {
+ $('#themer-popup dd.key').empty().prepend(key);
+ $('#themer-popup dt.key-type').empty().prepend(strs.template_called);
+ }
+
+ // parents
+ var parents = '';
+ parents = strs.parents +' <span class="parents">';
+ for(i=1;i<objs.length;i++) {
+ parents += i!=1 ? '&lt; ' : '';
+ parents += '<span class="parent" trig="'+ objs[i].id +'">'+ $(objs[i]).attr('thmr_key') +'</span> ';
+ }
+ parents += '</span>';
+
+ $('#themer-popup #parents').empty().prepend(parents);
+ $('#themer-popup span.parent').click(function() {
+ obj = $('#'+ $(this).attr('trig')).get(0).firstChild;
+ themerDoIt(obj);
+ });
+
+ if (vars == undefined) {
+ $('#themer-popup dd.candidates').empty();
+ $('#themer-popup div.attributes').empty();
+ $('#themer-popup div.used').empty();
+ }
+ else {
+ if (type == 'func') {
+ $('#themer-popup dt.candidates-type').empty().prepend(strs.candidate_functions);
+ $('#themer-popup dd.candidates').empty().prepend(vars.candidates);
+
+ $('#themer-popup div.attributes').empty().prepend('<h4>'+ strs.function_arguments + '</h4>' + vars.args);
+ $('#themer-popup div.used').empty();
+ }
+ else {
+ $('#themer-popup dt.candidates-type').empty().prepend(strs.candidate_files);
+ $('#themer-popup dd.candidates').empty().prepend(vars.candidates.join(", "));
+
+ $('#themer-popup div.attributes').empty().prepend('<h4>'+ strs.template_variables + '</h4>' + vars.arguments);
+ $('#themer-popup div.used').empty().prepend('<dt>'+ strs.file_used +'</dt><dd>'+ vars.used +'</dd>');
+ }
+ thmrRefreshCollapse();
+ }
+} \ No newline at end of file
diff --git a/devel_themer.module b/devel_themer.module
index 3ebb7e1..fe9e736 100644
--- a/devel_themer.module
+++ b/devel_themer.module
@@ -13,7 +13,9 @@ function devel_themer_init() {
$path = drupal_get_path('module', 'devel_themer');
drupal_add_css($path .'/devel_themer.css');
drupal_add_js($path .'/devel_themer.js');
-
+ drupal_add_js($path .'/jquery-ui-drag.min.js');
+ devel_themer_popup();
+
if (!devel_silent()) {
register_shutdown_function('devel_themer_shutdown');
}
@@ -55,7 +57,7 @@ function devel_theme_log() {
foreach ($GLOBALS['devel_theme_calls'] as $counter => $call) {
$id = "devel_theme_log_link_$counter";
$marker = "<div id=\"$id\" class=\"devel_theme_log_link\"></div>\n";
-
+
if (count($call['candidates']) > 1) {
$used = $call['used'];
foreach ($call['candidates'] as $key => $value) {
@@ -116,16 +118,16 @@ function devel_themer_preprocess($vars, $hook) {
// I found no other easy way to determine this. Patches welcome.
function phptemplate_render_template($file, $variables) {
$counter = devel_counter(FALSE);
-
+
$timer_name = "thmr_$counter";
timer_start($timer_name);
$output = theme_render_template($file, $variables);
$time = timer_stop($timer_name);
$GLOBALS['devel_theme_calls'][$counter]['time'] = $time['time'];
-
+
$GLOBALS['devel_theme_calls'][$counter]['used'] = $file;
$GLOBALS['devel_theme_calls'][$counter]['args'] = $variables;
-
+
// awful attempt to get position #2 in the assoc array $variables
$i=0;
foreach ($variables as $key => $var) {
@@ -135,7 +137,7 @@ function phptemplate_render_template($file, $variables) {
$i++;
}
list($prefix, $suffix) = devel_theme_call_marker($name, $counter, 'tpl');
- // drupal_add_js(array("thmr_$counter" => array('arguments' => $variables, 'candidates' => $GLOBALS['devel_theme_calls'][$counter]['candidates'], 'used' => $GLOBALS['devel_theme_calls'][$counter]['used'])), 'setting', 'header', FALSE, FALSE, FALSE);
+ drupal_add_js(array("thmr_$counter" => array('arguments' => devel_print_object($variables, '$', FALSE), 'candidates' => array_reverse($GLOBALS['devel_theme_calls'][$counter]['candidates']), 'used' => $GLOBALS['devel_theme_calls'][$counter]['used'])), 'setting', 'header', FALSE, FALSE, FALSE);
return $prefix. "\n ". $output. "\n". $suffix. "\n";
}
@@ -175,17 +177,17 @@ function devel_catch_theme_function() {
}
include_once($function_file);
}
-
+
$counter = devel_counter();
$output = NULL;
$name = $hook_registry_data['function'];
$skip = array('theme_hidden');
-
+
$timer_name = "thmr_$counter";
timer_start($timer_name);
$return = call_user_func_array($name, $args);
$time = timer_stop($timer_name);
-
+
if (!empty($return)) {
list($prefix, $suffix) = devel_theme_call_marker($name, $counter, 'func');
$start_return = substr($return, 0, 31);
@@ -194,7 +196,7 @@ function devel_catch_theme_function() {
// Pass the call to the original function. Wrap as needed.
if ($start_return != $start_prefix && !in_array($name, $skip)) {
$output = $prefix. "\n ". $return. $suffix. "\n";
- // drupal_add_js(array("thmr_$counter" => array('args' => $args, 'candidates' => $candidates)), 'setting', 'header', FALSE, FALSE, FALSE);
+ drupal_add_js(array("thmr_$counter" => array('args' => devel_print_object($args, NULL, FALSE), 'candidates' => $candidates)), 'setting', 'header', FALSE, FALSE, FALSE);
}
else {
$output = $return;
@@ -211,13 +213,13 @@ function devel_catch_theme_function() {
'used' => $call_theme_func,
'candidates' => is_array($trace[2]['args'][0]) ? $trace[2]['args'][0] : array($call_theme_func),
);
-
+
return $output;
}
/**
* An implementation of hook_footer(). Emit huge js array for the benefit of the popup.
- *
+ *
* @return void
**/
function devel_themer_footer() {
@@ -236,4 +238,68 @@ function devel_counter($increment = TRUE) {
$counter++;
}
return $counter;
+}
+
+/**
+ * Return the popup template
+ * placed here for easy editing
+ */
+function devel_themer_popup() {
+ $majorver = substr(VERSION, 0, strpos(VERSION, '.'));
+
+ // add translatable strings
+ drupal_add_js(array('thmrStrings' =>
+ array(
+ 'parents' => t('Parents: '),
+ 'function_called' => t('Function called: '),
+ 'template_called' => t('Template called: '),
+ 'candidate_files' => t('Candidate template files: '),
+ 'candidate_functions' => t('Candidate function names: '),
+ 'drupal_api_docs' => t('link to Drupal API documentation'),
+ 'function_arguments' => t('Function Arguments'),
+ 'template_variables' => t('Template Variables'),
+ 'file_used' => t('File used: '),
+ 'api_site' => variable_get('devel_api_site', 'http://api.drupal.org/'),
+ 'drupal_version' => $majorver,
+ ))
+ , 'setting');
+
+ $title = t('Drupal Themer Information');
+ $intro = t('Click on any element on the page to see the Drupal theme function or template that created it.');
+
+ $popup = <<<EOT
+ <div id="themer-popup">
+ <div class="topper">
+ <span class="close">X</span> $title
+ </div>
+ <div id="parents" class="row">
+
+ </div>
+ <div class="info row">
+ <div class="starter">$intro</div>
+ <dl>
+ <dt class="key-type">
+
+ </dt>
+ <dd class="key">
+
+ </dd>
+ <dt class="candidates-type">
+
+ </dt>
+ <dd class="candidates">
+
+ </dd>
+ <div class="used">
+ </div>
+ </dl>
+ </div><!-- /info -->
+ <div class="attributes row">
+
+ </div><!-- /attributes -->
+ </div><!-- /themer-popup -->
+EOT;
+
+ drupal_add_js(array('thmr_popup' => $popup), 'setting');
+
} \ No newline at end of file
diff --git a/jquery-ui-drag.min.js b/jquery-ui-drag.min.js
new file mode 100644
index 0000000..536ac79
--- /dev/null
+++ b/jquery-ui-drag.min.js
@@ -0,0 +1,44 @@
+/*
+ * jQuery UI 1.0 - New Wave User Interface
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ */
+(function($){$.ui=$.ui||{};$.extend($.ui,{plugin:{add:function(w,c,o,p){var a=$.ui[w].prototype;if(!a.plugins[c])a.plugins[c]=[];a.plugins[c].push([o,p]);},call:function(instance,name,arguments){var c=instance.plugins[name];if(!c)return;var o=instance.interaction?instance.interaction.options:instance.options;var e=instance.interaction?instance.interaction.element:instance.element;for(var i=0;i<c.length;i++){if(o[c[i][0]])c[i][1].apply(e,arguments);}}}});$.fn.mouseInteractionDestroy=function(){this.each(function(){if($.data(this,"ui-mouse"))$.data(this,"ui-mouse").destroy();});}
+$.ui.mouseInteraction=function(el,o){if(!o)var o={};this.element=el;$.data(this.element,"ui-mouse",this);this.options={};$.extend(this.options,o);$.extend(this.options,{handle:o.handle?($(o.handle,el)[0]?$(o.handle,el):$(el)):$(el),helper:o.helper||'original',preventionDistance:o.preventionDistance||0,dragPrevention:o.dragPrevention?o.dragPrevention.toLowerCase().split(','):['input','textarea','button','select','option'],cursorAt:{top:((o.cursorAt&&o.cursorAt.top)?o.cursorAt.top:0),left:((o.cursorAt&&o.cursorAt.left)?o.cursorAt.left:0),bottom:((o.cursorAt&&o.cursorAt.bottom)?o.cursorAt.bottom:0),right:((o.cursorAt&&o.cursorAt.right)?o.cursorAt.right:0)},cursorAtIgnore:(!o.cursorAt)?true:false,appendTo:o.appendTo||'parent'})
+o=this.options;if(!this.options.nonDestructive&&(o.helper=='clone'||o.helper=='original')){o.margins={top:parseInt($(el).css('marginTop'))||0,left:parseInt($(el).css('marginLeft'))||0,bottom:parseInt($(el).css('marginBottom'))||0,right:parseInt($(el).css('marginRight'))||0};if(o.cursorAt.top!=0)o.cursorAt.top=o.margins.top;if(o.cursorAt.left!=0)o.cursorAt.left+=o.margins.left;if(o.cursorAt.bottom!=0)o.cursorAt.bottom+=o.margins.bottom;if(o.cursorAt.right!=0)o.cursorAt.right+=o.margins.right;if(o.helper=='original')
+o.wasPositioned=$(el).css('position');}else{o.margins={top:0,left:0,right:0,bottom:0};}
+var self=this;this.mousedownfunc=function(e){return self.click.apply(self,[e]);}
+o.handle.bind('mousedown',this.mousedownfunc);if($.browser.msie)$(this.element).attr('unselectable','on');}
+$.extend($.ui.mouseInteraction.prototype,{plugins:{},currentTarget:null,lastTarget:null,timer:null,slowMode:false,init:false,destroy:function(){this.options.handle.unbind('mousedown',this.mousedownfunc);},trigger:function(e){return this.click.apply(this,arguments);},click:function(e){var o=this.options;window.focus();if(e.which!=1)return true;var targetName=(e.target)?e.target.nodeName.toLowerCase():e.srcElement.nodeName.toLowerCase();for(var i=0;i<o.dragPrevention.length;i++){if(targetName==o.dragPrevention[i])return true;}
+if(o.startCondition&&!o.startCondition.apply(this,[e]))return true;var self=this;this.mouseup=function(e){return self.stop.apply(self,[e]);}
+this.mousemove=function(e){return self.drag.apply(self,[e]);}
+var initFunc=function(){$(document).bind('mouseup',self.mouseup);$(document).bind('mousemove',self.mousemove);self.opos=[e.pageX,e.pageY];}
+if(o.preventionTimeout){if(this.timer)clearInterval(this.timer);this.timer=setTimeout(function(){initFunc();},o.preventionTimeout);return false;}
+initFunc();return false;},start:function(e){var o=this.options;var a=this.element;o.co=$(a).offset();this.helper=typeof o.helper=='function'?$(o.helper.apply(a,[e,this]))[0]:(o.helper=='clone'?$(a).clone()[0]:a);if(o.appendTo=='parent'){var cp=a.parentNode;while(cp){if(cp.style&&($(cp).css('position')=='relative'||$(cp).css('position')=='absolute')){o.pp=cp;o.po=$(cp).offset();o.ppOverflow=!!($(o.pp).css('overflow')=='auto'||$(o.pp).css('overflow')=='scroll');break;}
+cp=cp.parentNode?cp.parentNode:null;};if(!o.pp)o.po={top:0,left:0};}
+this.pos=[this.opos[0],this.opos[1]];this.rpos=[this.pos[0],this.pos[1]];if(o.cursorAtIgnore){o.cursorAt.left=this.pos[0]-o.co.left+o.margins.left;o.cursorAt.top=this.pos[1]-o.co.top+o.margins.top;}
+if(o.pp){this.pos[0]-=o.po.left;this.pos[1]-=o.po.top;}
+this.slowMode=(o.cursorAt&&(o.cursorAt.top-o.margins.top>0||o.cursorAt.bottom-o.margins.bottom>0)&&(o.cursorAt.left-o.margins.left>0||o.cursorAt.right-o.margins.right>0))?true:false;if(!o.nonDestructive)$(this.helper).css('position','absolute');if(o.helper!='original')$(this.helper).appendTo((o.appendTo=='parent'?a.parentNode:o.appendTo)).show();if(o.cursorAt.right&&!o.cursorAt.left)o.cursorAt.left=this.helper.offsetWidth+o.margins.right+o.margins.left-o.cursorAt.right;if(o.cursorAt.bottom&&!o.cursorAt.top)o.cursorAt.top=this.helper.offsetHeight+o.margins.top+o.margins.bottom-o.cursorAt.bottom;this.init=true;if(o._start)o._start.apply(a,[this.helper,this.pos,o.cursorAt,this,e]);this.helperSize={width:outerWidth(this.helper),height:outerHeight(this.helper)};return false;},stop:function(e){var o=this.options;var a=this.element;var self=this;$(document).unbind('mouseup',self.mouseup);$(document).unbind('mousemove',self.mousemove);if(this.init==false)return this.opos=this.pos=null;if(o._beforeStop)o._beforeStop.apply(a,[this.helper,this.pos,o.cursorAt,this,e]);if(this.helper!=a&&!o.beQuietAtEnd){$(this.helper).remove();this.helper=null;}
+if(!o.beQuietAtEnd){if(o._stop)o._stop.apply(a,[this.helper,this.pos,o.cursorAt,this,e]);}
+this.init=false;this.opos=this.pos=null;return false;},drag:function(e){if(!this.opos||($.browser.msie&&!e.button))return this.stop.apply(this,[e]);var o=this.options;this.pos=[e.pageX,e.pageY];if(this.rpos&&this.rpos[0]==this.pos[0]&&this.rpos[1]==this.pos[1])return false;this.rpos=[this.pos[0],this.pos[1]];if(o.pp){this.pos[0]-=o.po.left;this.pos[1]-=o.po.top;}
+if((Math.abs(this.rpos[0]-this.opos[0])>o.preventionDistance||Math.abs(this.rpos[1]-this.opos[1])>o.preventionDistance)&&this.init==false)
+this.start.apply(this,[e]);else{if(this.init==false)return false;}
+if(o._drag)o._drag.apply(this.element,[this.helper,this.pos,o.cursorAt,this,e]);return false;}});var num=function(el,prop){return parseInt($.css(el.jquery?el[0]:el,prop))||0;};function outerWidth(el){var $el=$(el),ow=$el.width();for(var i=0,props=['borderLeftWidth','paddingLeft','paddingRight','borderRightWidth'];i<props.length;i++)
+ow+=num($el,props[i]);return ow;}
+function outerHeight(el){var $el=$(el),oh=$el.width();for(var i=0,props=['borderTopWidth','paddingTop','paddingBottom','borderBottomWidth'];i<props.length;i++)
+oh+=num($el,props[i]);return oh;}})(jQuery);
+(function($){$.extend($.expr[':'],{draggable:"(' '+a.className+' ').indexOf(' ui-draggable ')"});var methods="destroy,enable,disable".split(",");for(var i=0;i<methods.length;i++){var cur=methods[i],f;eval('f = function() { var a = arguments; return this.each(function() { if(jQuery(this).is(".ui-draggable")) jQuery.data(this, "ui-draggable")["'+cur+'"](a); }); }');$.fn["draggable"+cur.substr(0,1).toUpperCase()+cur.substr(1)]=f;};$.fn.draggableInstance=function(){if($(this[0]).is(".ui-draggable"))return $.data(this[0],"ui-draggable");return false;};$.fn.draggable=function(o){return this.each(function(){if(!$(this).is(".ui-draggable"))new $.ui.draggable(this,o);});}
+$.ui.ddmanager={current:null,droppables:[],prepareOffsets:function(t,e){var dropTop=$.ui.ddmanager.dropTop=[];var dropLeft=$.ui.ddmanager.dropLeft;var m=$.ui.ddmanager.droppables;for(var i=0;i<m.length;i++){if(m[i].item.disabled)continue;m[i].offset=$(m[i].item.element).offset();if(t&&m[i].item.options.accept(t.element))
+m[i].item.activate.call(m[i].item,e);}},fire:function(oDrag,e){var oDrops=$.ui.ddmanager.droppables;var oOvers=$.grep(oDrops,function(oDrop){if(!oDrop.item.disabled&&$.ui.intersect(oDrag,oDrop,oDrop.item.options.tolerance))
+oDrop.item.drop.call(oDrop.item,e);});$.each(oDrops,function(i,oDrop){if(!oDrop.item.disabled&&oDrop.item.options.accept(oDrag.element)){oDrop.out=1;oDrop.over=0;oDrop.item.deactivate.call(oDrop.item,e);}});},update:function(oDrag,e){if(oDrag.options.refreshPositions)$.ui.ddmanager.prepareOffsets();var oDrops=$.ui.ddmanager.droppables;var oOvers=$.grep(oDrops,function(oDrop){if(oDrop.item.disabled)return false;var isOver=$.ui.intersect(oDrag,oDrop,oDrop.item.options.tolerance)
+if(!isOver&&oDrop.over==1){oDrop.out=1;oDrop.over=0;oDrop.item.out.call(oDrop.item,e);}
+return isOver;});$.each(oOvers,function(i,oOver){if(oOver.over==0){oOver.out=0;oOver.over=1;oOver.item.over.call(oOver.item,e);}});}};$.ui.draggable=function(el,o){var options={};$.extend(options,o);var self=this;$.extend(options,{_start:function(h,p,c,t,e){self.start.apply(t,[self,e]);},_beforeStop:function(h,p,c,t,e){self.stop.apply(t,[self,e]);},_drag:function(h,p,c,t,e){self.drag.apply(t,[self,e]);},startCondition:function(e){return!(e.target.className.indexOf("ui-resizable-handle")!=-1||self.disabled);}});$.data(el,"ui-draggable",this);if(options.ghosting==true)options.helper='clone';$(el).addClass("ui-draggable");this.interaction=new $.ui.mouseInteraction(el,options);}
+$.extend($.ui.draggable.prototype,{plugins:{},currentTarget:null,lastTarget:null,destroy:function(){$(this.interaction.element).removeClass("ui-draggable").removeClass("ui-draggable-disabled");this.interaction.destroy();},enable:function(){$(this.interaction.element).removeClass("ui-draggable-disabled");this.disabled=false;},disable:function(){$(this.interaction.element).addClass("ui-draggable-disabled");this.disabled=true;},prepareCallbackObj:function(self){return{helper:self.helper,position:{left:self.pos[0],top:self.pos[1]},offset:self.options.cursorAt,draggable:self,options:self.options}},start:function(that,e){var o=this.options;$.ui.ddmanager.current=this;$.ui.plugin.call(that,'start',[e,that.prepareCallbackObj(this)]);$(this.element).triggerHandler("dragstart",[e,that.prepareCallbackObj(this)],o.start);if(this.slowMode&&$.ui.droppable&&!o.dropBehaviour)
+$.ui.ddmanager.prepareOffsets(this,e);return false;},stop:function(that,e){var o=this.options;$.ui.plugin.call(that,'stop',[e,that.prepareCallbackObj(this)]);$(this.element).triggerHandler("dragstop",[e,that.prepareCallbackObj(this)],o.stop);if(this.slowMode&&$.ui.droppable&&!o.dropBehaviour)
+$.ui.ddmanager.fire(this,e);$.ui.ddmanager.current=null;$.ui.ddmanager.last=this;return false;},drag:function(that,e){var o=this.options;$.ui.ddmanager.update(this,e);this.pos=[this.pos[0]-o.cursorAt.left,this.pos[1]-o.cursorAt.top];$.ui.plugin.call(that,'drag',[e,that.prepareCallbackObj(this)]);var nv=$(this.element).triggerHandler("drag",[e,that.prepareCallbackObj(this)],o.drag);var nl=(nv&&nv.left)?nv.left:this.pos[0];var nt=(nv&&nv.top)?nv.top:this.pos[1];$(this.helper).css('left',nl+'px').css('top',nt+'px');return false;}});})(jQuery);
+(function($){$.ui.plugin.add("draggable","stop","effect",function(e,ui){var t=ui.helper;if(ui.options.effect[1]){if(t!=this){ui.options.beQuietAtEnd=true;switch(ui.options.effect[1]){case'fade':$(t).fadeOut(300,function(){$(this).remove();});break;default:$(t).remove();break;}}}});$.ui.plugin.add("draggable","start","effect",function(e,ui){if(ui.options.effect[0]){switch(ui.options.effect[0]){case'fade':$(ui.helper).hide().fadeIn(300);break;}}});$.ui.plugin.add("draggable","start","cursor",function(e,ui){var t=$('body');if(t.css("cursor"))ui.options.ocursor=t.css("cursor");t.css("cursor",ui.options.cursor);});$.ui.plugin.add("draggable","stop","cursor",function(e,ui){if(ui.options.ocursor)$('body').css("cursor",ui.options.ocursor);});$.ui.plugin.add("draggable","start","zIndex",function(e,ui){var t=$(ui.helper);if(t.css("zIndex"))ui.options.ozIndex=t.css("zIndex");t.css('zIndex',ui.options.zIndex);});$.ui.plugin.add("draggable","stop","zIndex",function(e,ui){if(ui.options.ozIndex)$(ui.helper).css('zIndex',ui.options.ozIndex);});$.ui.plugin.add("draggable","start","opacity",function(e,ui){var t=$(ui.helper);if(t.css("opacity"))ui.options.oopacity=t.css("opacity");t.css('opacity',ui.options.opacity);});$.ui.plugin.add("draggable","stop","opacity",function(e,ui){if(ui.options.oopacity)$(ui.helper).css('opacity',ui.options.oopacity);});$.ui.plugin.add("draggable","stop","revert",function(e,ui){var o=ui.options;var rpos={left:0,top:0};o.beQuietAtEnd=true;if(ui.helper!=this){rpos=$(ui.draggable.sorthelper||this).offset({border:false});var nl=rpos.left-o.po.left-o.margins.left;var nt=rpos.top-o.po.top-o.margins.top;}else{var nl=o.co.left-(o.po?o.po.left:0);var nt=o.co.top-(o.po?o.po.top:0);}
+var self=ui.draggable;$(ui.helper).animate({left:nl,top:nt},500,function(){if(o.wasPositioned)$(self.element).css('position',o.wasPositioned);if(o.stop)o.stop.apply(self.element,[self.helper,self.pos,[o.co.left-o.po.left,o.co.top-o.po.top],self]);if(self.helper!=self.element)window.setTimeout(function(){$(self.helper).remove();},0);});});$.ui.plugin.add("draggable","start","iframeFix",function(e,ui){var o=ui.options;if(!ui.draggable.slowMode){if(o.iframeFix.constructor==Array){for(var i=0;i<o.iframeFix.length;i++){var co=$(o.iframeFix[i]).offset({border:false});$("<div class='DragDropIframeFix' style='background: #fff;'></div>").css("width",$(o.iframeFix[i])[0].offsetWidth+"px").css("height",$(o.iframeFix[i])[0].offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",co.top+"px").css("left",co.left+"px").appendTo("body");}}else{$("iframe").each(function(){var co=$(this).offset({border:false});$("<div class='DragDropIframeFix' style='background: #fff;'></div>").css("width",this.offsetWidth+"px").css("height",this.offsetHeight+"px").css("position","absolute").css("opacity","0.001").css("z-index","1000").css("top",co.top+"px").css("left",co.left+"px").appendTo("body");});}}});$.ui.plugin.add("draggable","stop","iframeFix",function(e,ui){if(ui.options.iframeFix)$("div.DragDropIframeFix").each(function(){this.parentNode.removeChild(this);});});$.ui.plugin.add("draggable","start","containment",function(e,ui){var o=ui.options;if(!o.cursorAtIgnore||o.containment.left!=undefined||o.containment.constructor==Array)return;if(o.containment=='parent')o.containment=this.parentNode;if(o.containment=='document'){o.containment=[0-o.margins.left,0-o.margins.top,$(document).width()-o.margins.right,($(document).height()||document.body.parentNode.scrollHeight)-o.margins.bottom];}else{var ce=$(o.containment)[0];var co=$(o.containment).offset({border:false});o.containment=[co.left-o.margins.left,co.top-o.margins.top,co.left+(ce.offsetWidth||ce.scrollWidth)-o.margins.right,co.top+(ce.offsetHeight||ce.scrollHeight)-o.margins.bottom];}});$.ui.plugin.add("draggable","drag","containment",function(e,ui){var o=ui.options;if(!o.cursorAtIgnore)return;var h=$(ui.helper);var c=o.containment;if(c.constructor==Array){if((ui.draggable.pos[0]<c[0]-o.po.left))ui.draggable.pos[0]=c[0]-o.po.left;if((ui.draggable.pos[1]<c[1]-o.po.top))ui.draggable.pos[1]=c[1]-o.po.top;if(ui.draggable.pos[0]+h[0].offsetWidth>c[2]-o.po.left)ui.draggable.pos[0]=c[2]-o.po.left-h[0].offsetWidth;if(ui.draggable.pos[1]+h[0].offsetHeight>c[3]-o.po.top)ui.draggable.pos[1]=c[3]-o.po.top-h[0].offsetHeight;}else{if(c.left&&(ui.draggable.pos[0]<c.left))ui.draggable.pos[0]=c.left;if(c.top&&(ui.draggable.pos[1]<c.top))ui.draggable.pos[1]=c.top;var p=$(o.pp);if(c.right&&ui.draggable.pos[0]+h[0].offsetWidth>p[0].offsetWidth-c.right)ui.draggable.pos[0]=(p[0].offsetWidth-c.right)-h[0].offsetWidth;if(c.bottom&&ui.draggable.pos[1]+h[0].offsetHeight>p[0].offsetHeight-c.bottom)ui.draggable.pos[1]=(p[0].offsetHeight-c.bottom)-h[0].offsetHeight;}});$.ui.plugin.add("draggable","drag","grid",function(e,ui){var o=ui.options;if(!o.cursorAtIgnore)return;ui.draggable.pos[0]=o.co.left+o.margins.left-o.po.left+Math.round((ui.draggable.pos[0]-o.co.left-o.margins.left+o.po.left)/o.grid[0])*o.grid[0];ui.draggable.pos[1]=o.co.top+o.margins.top-o.po.top+Math.round((ui.draggable.pos[1]-o.co.top-o.margins.top+o.po.top)/o.grid[1])*o.grid[1];});$.ui.plugin.add("draggable","drag","axis",function(e,ui){var o=ui.options;if(!o.cursorAtIgnore)return;if(o.constraint)o.axis=o.constraint;o.axis?(o.axis=='x'?ui.draggable.pos[1]=o.co.top-o.margins.top-o.po.top:ui.draggable.pos[0]=o.co.left-o.margins.left-o.po.left):null;});$.ui.plugin.add("draggable","drag","scroll",function(e,ui){var o=ui.options;o.scrollSensitivity=o.scrollSensitivity||20;o.scrollSpeed=o.scrollSpeed||20;if(o.pp&&o.ppOverflow){}else{if((ui.draggable.rpos[1]-$(window).height())-$(document).scrollTop()>-o.scrollSensitivity)window.scrollBy(0,o.scrollSpeed);if(ui.draggable.rpos[1]-$(document).scrollTop()<o.scrollSensitivity)window.scrollBy(0,-o.scrollSpeed);if((ui.draggable.rpos[0]-$(window).width())-$(document).scrollLeft()>-o.scrollSensitivity)window.scrollBy(o.scrollSpeed,0);if(ui.draggable.rpos[0]-$(document).scrollLeft()<o.scrollSensitivity)window.scrollBy(-o.scrollSpeed,0);}});$.ui.plugin.add("draggable","drag","wrapHelper",function(e,ui){var o=ui.options;if(o.cursorAtIgnore)return;var t=ui.helper;if(!o.pp||!o.ppOverflow){var wx=$(window).width()-($.browser.mozilla?20:0);var sx=$(document).scrollLeft();var wy=$(window).height();var sy=$(document).scrollTop();}else{var wx=o.pp.offsetWidth+o.po.left-20;var sx=o.pp.scrollLeft;var wy=o.pp.offsetHeight+o.po.top-20;var sy=o.pp.scrollTop;}
+ui.draggable.pos[0]-=((ui.draggable.rpos[0]-o.cursorAt.left-wx+t.offsetWidth+o.margins.right)-sx>0||(ui.draggable.rpos[0]-o.cursorAt.left+o.margins.left)-sx<0)?(t.offsetWidth+o.margins.left+o.margins.right-o.cursorAt.left*2):0;ui.draggable.pos[1]-=((ui.draggable.rpos[1]-o.cursorAt.top-wy+t.offsetHeight+o.margins.bottom)-sy>0||(ui.draggable.rpos[1]-o.cursorAt.top+o.margins.top)-sy<0)?(t.offsetHeight+o.margins.top+o.margins.bottom-o.cursorAt.top*2):0;});})(jQuery);
+(function($){$.ui.plugin.add("droppable","activate","activeClass",function(e,ui){$(this).addClass(ui.options.activeClass);});$.ui.plugin.add("droppable","deactivate","activeClass",function(e,ui){$(this).removeClass(ui.options.activeClass);});$.ui.plugin.add("droppable","drop","activeClass",function(e,ui){$(this).removeClass(ui.options.activeClass);});$.ui.plugin.add("droppable","over","hoverClass",function(e,ui){$(this).addClass(ui.options.hoverClass);});$.ui.plugin.add("droppable","out","hoverClass",function(e,ui){$(this).removeClass(ui.options.hoverClass);});$.ui.plugin.add("droppable","drop","hoverClass",function(e,ui){$(this).removeClass(ui.options.hoverClass);});})(jQuery); \ No newline at end of file