refactored js, split into more files (much more manageable). tested
116
Makefile
|
@ -1,64 +1,90 @@
|
|||
|
||||
SRC_DIR = src
|
||||
EXAMPLES_DIR = examples
|
||||
BUILD_DIR = build
|
||||
DIST_DIR = dist
|
||||
|
||||
JS_SRC_FILES = \
|
||||
${SRC_DIR}/main.js \
|
||||
${SRC_DIR}/grid.js \
|
||||
${SRC_DIR}/agenda.js \
|
||||
${SRC_DIR}/view.js \
|
||||
${SRC_DIR}/selection_util.js \
|
||||
${SRC_DIR}/util.js
|
||||
|
||||
CSS_SRC_FILES = \
|
||||
${SRC_DIR}/css/main.css \
|
||||
${SRC_DIR}/css/grid.css \
|
||||
${SRC_DIR}/css/agenda.css
|
||||
|
||||
DEMOS_DIR = demos
|
||||
OTHER_FILES = \
|
||||
${SRC_DIR}/jquery \
|
||||
changelog.txt
|
||||
changelog.txt \
|
||||
MIT-LICENSE.txt \
|
||||
GPL-LICENSE.txt
|
||||
|
||||
VER = `cat version.txt`
|
||||
VER = $$(cat version.txt)
|
||||
VER_SED = sed s/@VERSION/"${VER}"/
|
||||
DATE = `git log -1 | grep Date: | sed 's/[^:]*: *//'`
|
||||
DATE = $$(git log -1 --pretty=format:%ad)
|
||||
DATE_SED = sed s/@DATE/"${DATE}"/
|
||||
|
||||
JQ = $$(sed -n "s/.*JQUERY\s*=\s*[\"']\(.*\)[\"'].*/\1/p" "${SRC_DIR}/_loader.js")
|
||||
JQUI = $$(sed -n "s/.*JQUERY_UI\s*=\s*[\"']\(.*\)[\"'].*/\1/p" "${SRC_DIR}/_loader.js")
|
||||
|
||||
DEMO_FILES = $$(cd ${DEMOS_DIR}; find . -mindepth 1 -maxdepth 1 -type f)
|
||||
DEMO_SUBDIRS = $$(cd ${DEMOS_DIR}; find . -mindepth 1 -maxdepth 1 -type d)
|
||||
DEMO_RE = \(<script[^>]*_loader\.js[^>]*><\/script>\|<!--\[\[\|\]\]-->\)\s*
|
||||
DEMO_SED = sed -n "1h;1!H;\$${;g;s/${DEMO_RE}//g;p;}"
|
||||
|
||||
JS_SED = sed -n "s/\s*js([\"']\(.*\)[\"']).*/\1/p"
|
||||
CSS_SED = sed -n "s/\s*css([\"']\(.*\)[\"']).*/\1/p"
|
||||
|
||||
concat_js = \
|
||||
files=$$(cat "$(1)/_loader.js" | ${JS_SED}); \
|
||||
if [ -f "$(1)/intro.js" ]; then \
|
||||
files="intro.js $$files"; \
|
||||
fi; \
|
||||
if [ -f "$(1)/outro.js" ]; then \
|
||||
files="$$files outro.js"; \
|
||||
fi; \
|
||||
old=$$PWD; \
|
||||
(cd "$(1)"; cat $$files; cd "$$old") \
|
||||
| ${VER_SED} \
|
||||
| ${DATE_SED} \
|
||||
> "$(2)"
|
||||
|
||||
concat_css = \
|
||||
files=$$(cat "$(1)/_loader.js" | ${CSS_SED}); \
|
||||
if [ "$$files" ]; then \
|
||||
old=$$PWD; \
|
||||
(cd "$(1)"; cat $$files; cd "$$old") \
|
||||
| ${VER_SED} \
|
||||
| ${DATE_SED} \
|
||||
> "$(2)"; \
|
||||
fi
|
||||
|
||||
zip:
|
||||
@rm -rf ${BUILD_DIR}/fullcalendar
|
||||
@rm -rf ${BUILD_DIR}/fullcalendar-*
|
||||
@mkdir -p ${BUILD_DIR}/fullcalendar
|
||||
@mkdir -p ${BUILD_DIR}/fullcalendar/fullcalendar/
|
||||
|
||||
@echo "building js..."
|
||||
@cat ${SRC_DIR}/misc/head.txt ${JS_SRC_FILES} ${SRC_DIR}/misc/foot.txt \
|
||||
| ${VER_SED} | ${DATE_SED} \
|
||||
> ${BUILD_DIR}/fullcalendar/fullcalendar.js
|
||||
@cat ${SRC_DIR}/gcal.js \
|
||||
| ${VER_SED} | ${DATE_SED} \
|
||||
> ${BUILD_DIR}/fullcalendar/gcal.js
|
||||
@echo "building core..."
|
||||
@$(call concat_js,${SRC_DIR},"${BUILD_DIR}/fullcalendar/fullcalendar/fullcalendar.js")
|
||||
@$(call concat_css,${SRC_DIR},"${BUILD_DIR}/fullcalendar/fullcalendar/fullcalendar.css")
|
||||
|
||||
@echo "compressing js..."
|
||||
@java -jar ${BUILD_DIR}/compiler.jar --js ${BUILD_DIR}/fullcalendar/fullcalendar.js \
|
||||
> ${BUILD_DIR}/fullcalendar/fullcalendar.min.js
|
||||
@echo "compressing core js..."
|
||||
@java -jar ${BUILD_DIR}/compiler.jar --warning_level VERBOSE --jscomp_off checkTypes --externs build/externs.js \
|
||||
--js ${BUILD_DIR}/fullcalendar/fullcalendar/fullcalendar.js \
|
||||
> ${BUILD_DIR}/fullcalendar/fullcalendar/fullcalendar.min.js; \
|
||||
|
||||
@echo "building css..."
|
||||
@cat ${CSS_SRC_FILES} \
|
||||
| ${VER_SED} | ${DATE_SED} \
|
||||
> ${BUILD_DIR}/fullcalendar/fullcalendar.css
|
||||
|
||||
@echo "building examples..."
|
||||
@mkdir -p ${BUILD_DIR}/fullcalendar/examples
|
||||
@for f in `cd ${EXAMPLES_DIR}; find . -mindepth 1 -maxdepth 1 -type f`; do \
|
||||
cat ${EXAMPLES_DIR}/$$f \
|
||||
| sed -n '1h;1!H;$${;g;s/<!--\s*<src>.*<\/src>\s*-->\s*//g;p;}' \
|
||||
| sed -n '1h;1!H;$${;g;s/<!--\s*<dist>\s*//g;p;}' \
|
||||
| sed -n '1h;1!H;$${;g;s/<\/dist>\s*-->\s*//g;p;}' \
|
||||
> ${BUILD_DIR}/fullcalendar/examples/$$f; \
|
||||
@echo "building plugins..."
|
||||
@for loader in ${SRC_DIR}/*/_loader.js; do \
|
||||
dir=`dirname $$loader`; \
|
||||
name=`basename $$dir`; \
|
||||
$(call concat_js,$$dir,"${BUILD_DIR}/fullcalendar/fullcalendar/$$name.js"); \
|
||||
done
|
||||
@for d in `cd ${EXAMPLES_DIR}; find . -mindepth 1 -maxdepth 1 -type d`; do \
|
||||
cp -r ${EXAMPLES_DIR}/$$d ${BUILD_DIR}/fullcalendar/examples/$$d; \
|
||||
|
||||
@echo "copying jquery..."
|
||||
@mkdir -p ${BUILD_DIR}/fullcalendar/jquery
|
||||
@cp lib/${JQ} ${BUILD_DIR}/fullcalendar/jquery
|
||||
@cp lib/${JQUI} ${BUILD_DIR}/fullcalendar/jquery
|
||||
|
||||
@echo "building demos..."
|
||||
@mkdir -p ${BUILD_DIR}/fullcalendar/demos
|
||||
@for f in ${DEMO_FILES}; do \
|
||||
cat ${DEMOS_DIR}/$$f \
|
||||
| ${DEMO_SED} \
|
||||
| sed "s/jquery\.js/${JQ}/" \
|
||||
| sed "s/jquery-ui\.js/${JQUI}/" \
|
||||
> ${BUILD_DIR}/fullcalendar/demos/$$f; \
|
||||
done
|
||||
@for d in ${DEMO_SUBDIRS}; do \
|
||||
cp -r ${DEMOS_DIR}/$$d ${BUILD_DIR}/fullcalendar/demos/$$d; \
|
||||
done
|
||||
|
||||
@echo "copying other files..."
|
||||
|
|
1
build/externs.js
Normal file
|
@ -0,0 +1 @@
|
|||
var jQuery;
|
|
@ -1,27 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
|
@ -1,27 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
|
@ -1,27 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
|
@ -1,27 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
67
demos/gcal.html
Normal file
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<script type='text/javascript' src='../src/gcal/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/gcal.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
|
||||
// US Holidays
|
||||
events: $.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic'),
|
||||
|
||||
eventClick: function(event) {
|
||||
// opens events in a popup window
|
||||
window.open(event.url, 'gcalevent', 'width=700,height=600');
|
||||
return false;
|
||||
},
|
||||
|
||||
loading: function(bool) {
|
||||
if (bool) {
|
||||
$('#loading').show();
|
||||
}else{
|
||||
$('#loading').hide();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='loading' style='display:none'>loading...</div>
|
||||
<div id='calendar'></div>
|
||||
</body>
|
||||
</html>
|
63
demos/json.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
|
||||
editable: true,
|
||||
|
||||
events: "json-events.php",
|
||||
|
||||
eventDrop: function(event, delta) {
|
||||
alert(event.title + ' was moved ' + delta + ' days\n' +
|
||||
'(should probably update your database)');
|
||||
},
|
||||
|
||||
loading: function(bool) {
|
||||
if (bool) $('#loading').show();
|
||||
else $('#loading').hide();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='loading' style='display:none'>loading...</div>
|
||||
<div id='calendar'></div>
|
||||
<p>json-events.php needs to be running in the same directory.</p>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 180 B |
BIN
demos/redmond/images/ui-bg_flat_55_fbec88_40x100.png
Normal file
After Width: | Height: | Size: 182 B |
Before Width: | Height: | Size: 124 B After Width: | Height: | Size: 124 B |
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 123 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 104 B |
Before Width: | Height: | Size: 88 B After Width: | Height: | Size: 88 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
BIN
demos/redmond/images/ui-icons_f9bd01_256x240.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
|
@ -1,7 +1,11 @@
|
|||
/*
|
||||
* jQuery UI CSS Framework
|
||||
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
|
||||
* jQuery UI CSS Framework @VERSION
|
||||
*
|
||||
* 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/Theming/API
|
||||
*/
|
||||
|
||||
/* Layout helpers
|
||||
|
@ -37,11 +41,15 @@
|
|||
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* jQuery UI CSS Framework
|
||||
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
|
||||
* jQuery UI CSS Framework @VERSION
|
||||
*
|
||||
* 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/Theming/API
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&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
|
||||
*/
|
||||
|
||||
|
@ -49,6 +57,7 @@
|
|||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget { font-family: Lucida Grande, Lucida Sans, 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: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
|
||||
.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
|
||||
.ui-widget-content a { color: #222222; }
|
||||
|
@ -57,23 +66,24 @@
|
|||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; }
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; 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 #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; text-decoration: none; }
|
||||
.ui-widget :active { outline: none; }
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
|
||||
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
|
||||
.ui-state-error, .ui-widget-content .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 { color: #cd0a0a; }
|
||||
.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
|
||||
.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||
.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
|
||||
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.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
|
||||
----------------------------------*/
|
||||
|
@ -224,6 +234,8 @@
|
|||
.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; }
|
||||
|
@ -268,139 +280,52 @@
|
|||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; }
|
||||
.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
|
||||
.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
|
||||
.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||
.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; }
|
||||
.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||
.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; }
|
||||
.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; }
|
||||
.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; }
|
||||
.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
|
||||
.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
|
||||
.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
|
||||
.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
|
||||
.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; }
|
||||
.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
|
||||
.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
|
||||
.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
|
||||
.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
|
||||
|
||||
/* 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; }/* Accordion
|
||||
----------------------------------*/
|
||||
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
||||
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
||||
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
|
||||
.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
|
||||
----------------------------------*/
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||
.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
|
||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||
.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
|
||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||
.ui-datepicker td { border: 0; padding: 1px; }
|
||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||
.ui-datepicker-row-break { clear:both; width:100%; }
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl { direction: rtl; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
|
||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||
.ui-datepicker-cover {
|
||||
display: none; /*sorry for IE5*/
|
||||
display/**/: block; /*sorry for IE5*/
|
||||
position: absolute; /*must have*/
|
||||
z-index: -1; /*must have*/
|
||||
filter: mask(); /*must have*/
|
||||
top: -4px; /*must have*/
|
||||
left: -4px; /*must have*/
|
||||
width: 200px; /*must have*/
|
||||
height: 200px; /*must have*/
|
||||
}/* Dialog
|
||||
----------------------------------*/
|
||||
.ui-dialog { position: relative; padding: .2em; width: 300px; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
/* Progressbar
|
||||
----------------------------------*/
|
||||
.ui-progressbar { height:2em; text-align: left; }
|
||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
|
||||
----------------------------------*/
|
||||
.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 Resizable @VERSION
|
||||
*
|
||||
* 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/Resizable#theming
|
||||
*/
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
|
||||
----------------------------------*/
|
||||
.ui-slider { position: relative; text-align: left; }
|
||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
|
||||
|
||||
.ui-slider-horizontal { height: .8em; }
|
||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||
|
||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
|
||||
----------------------------------*/
|
||||
.ui-tabs { padding: .2em; zoom: 1; }
|
||||
.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
||||
* jQuery UI Tabs @VERSION
|
||||
*
|
||||
* 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/Tabs#theming
|
||||
*/
|
||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tabs .ui-tabs-hide { display: none !important; }
|
|
@ -1,27 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
|
@ -2,27 +2,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='redmond/theme.css' />
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../src/_loader.js'></script>
|
||||
<!--[[
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar/fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript' src='../jquery/jquery-ui.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar/fullcalendar.min.js'></script>
|
||||
]]-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/gcal.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
<script type='text/javascript' src='../gcal.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
|
||||
// US Holidays
|
||||
events: $.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic'),
|
||||
|
||||
eventClick: function(event) {
|
||||
// opens events in a popup window
|
||||
window.open(event.url, 'gcalevent', 'width=700,height=600');
|
||||
return false;
|
||||
},
|
||||
|
||||
loading: function(bool) {
|
||||
if (bool) {
|
||||
$('#loading').show();
|
||||
}else{
|
||||
$('#loading').hide();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='loading' style='display:none'>loading...</div>
|
||||
<div id='calendar'></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,77 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<!--<src>-->
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/main.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/grid.css' />
|
||||
<link rel='stylesheet' type='text/css' href='../src/css/agenda.css' />
|
||||
<script type='text/javascript' src='../src/jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../src/jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../src/main.js'></script>
|
||||
<script type='text/javascript' src='../src/grid.js'></script>
|
||||
<script type='text/javascript' src='../src/agenda.js'></script>
|
||||
<script type='text/javascript' src='../src/view.js'></script>
|
||||
<script type='text/javascript' src='../src/selection_util.js'></script>
|
||||
<script type='text/javascript' src='../src/util.js'></script>
|
||||
<!--</src>-->
|
||||
<!--
|
||||
<dist>
|
||||
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
|
||||
<script type='text/javascript' src='../jquery/jquery.js'></script>
|
||||
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
|
||||
<script type='text/javascript' src='../fullcalendar.min.js'></script>
|
||||
</dist>
|
||||
-->
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
|
||||
editable: true,
|
||||
|
||||
events: "json-events.php",
|
||||
|
||||
eventDrop: function(event, delta) {
|
||||
alert(event.title + ' was moved ' + delta + ' days\n' +
|
||||
'(should probably update your database)');
|
||||
},
|
||||
|
||||
loading: function(bool) {
|
||||
if (bool) $('#loading').show();
|
||||
else $('#loading').hide();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style type='text/css'>
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='loading' style='display:none'>loading...</div>
|
||||
<div id='calendar'></div>
|
||||
<p>json-events.php needs to be running in the same directory.</p>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 213 B |
Before Width: | Height: | Size: 5.2 KiB |
|
@ -1,39 +1,41 @@
|
|||
/*!
|
||||
* jQuery UI 1.8.1
|
||||
* jQuery UI 1.8.4
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* 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
|
||||
*/
|
||||
jQuery.ui||function(c){c.ui={version:"1.8.1",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")=="hidden")return false;
|
||||
b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,
|
||||
PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||
|
||||
/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==
|
||||
undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&
|
||||
!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}(jQuery);
|
||||
(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.4",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,
|
||||
b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,
|
||||
CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable",
|
||||
"off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,
|
||||
"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=
|
||||
parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c.style(this,h,d(this,f)+"px")})};c.fn["outer"+
|
||||
b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c.style(this,h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==
|
||||
b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
|
||||
;/*!
|
||||
* jQuery UI Widget 1.8.1
|
||||
* jQuery UI Widget 1.8.4
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* 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/Widget
|
||||
*/
|
||||
(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
|
||||
b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
|
||||
b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
|
||||
this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
|
||||
(function(b,j){var k=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return k.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);
|
||||
b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):
|
||||
this.each(function(){var g=b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});
|
||||
this._create();this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}b.each(d,function(f,
|
||||
h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
|
||||
b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
|
||||
;/*!
|
||||
* jQuery UI Mouse 1.8.1
|
||||
* jQuery UI Mouse 1.8.4
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* 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/Mouse
|
||||
*
|
||||
|
@ -46,11 +48,11 @@ return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._m
|
|||
this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
|
||||
a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
|
||||
;/*
|
||||
* jQuery UI Draggable 1.8.1
|
||||
* jQuery UI Draggable 1.8.4
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* 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/Draggables
|
||||
*
|
||||
|
@ -78,7 +80,7 @@ f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this
|
|||
this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
|
||||
Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
|
||||
this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
|
||||
this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.1"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
|
||||
this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.4"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
|
||||
if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
|
||||
c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
|
||||
1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
|
||||
|
@ -95,11 +97,11 @@ p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.
|
|||
(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
|
||||
10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
|
||||
;/*
|
||||
* jQuery UI Resizable 1.8.1
|
||||
* jQuery UI Resizable 1.8.4
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
* 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/Resizables
|
||||
*
|
||||
|
@ -108,37 +110,37 @@ p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.
|
|||
* jquery.ui.mouse.js
|
||||
* jquery.ui.widget.js
|
||||
*/
|
||||
(function(d){d.widget("ui.resizable",d.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");d.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
|
||||
_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&d.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(d('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
|
||||
(function(e){e.widget("ui.resizable",e.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");e.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
|
||||
_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&e.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
|
||||
top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
|
||||
this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
|
||||
nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e<c.length;e++){var g=d.trim(c[e]),f=d('<div class="ui-resizable-handle '+("ui-resizable-"+g)+'"></div>');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
|
||||
String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection();
|
||||
this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
|
||||
if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
|
||||
e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset=
|
||||
this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
|
||||
this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
|
||||
b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height;
|
||||
g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
|
||||
b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top=
|
||||
a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidth<b.width,g=k(b.height)&&a.maxHeight&&a.maxHeight<b.height,f=k(b.width)&&a.minWidth&&a.minWidth>b.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
|
||||
l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var e=[c.css("borderTopWidth"),
|
||||
c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],g=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=d.map(e,function(f,h){f=parseInt(f,10)||0;h=parseInt(g[h],10)||0;return f+h})}d.browser.msie&&(d(b).is(":hidden")||d(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
|
||||
this.element.offset();if(this._helper){this.helper=this.helper||d('<div style="overflow:hidden;"></div>');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
|
||||
a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this,
|
||||
arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable,
|
||||
{version:"1.8.1"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)});
|
||||
else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&&
|
||||
d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a=
|
||||
d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing,
|
||||
step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=
|
||||
d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset;
|
||||
var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left:
|
||||
a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top-
|
||||
e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition,
|
||||
g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,
|
||||
display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b=
|
||||
d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height=
|
||||
e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
|
||||
this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
|
||||
nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d<c.length;d++){var f=e.trim(c[d]),g=e('<div class="ui-resizable-handle '+("ui-resizable-"+f)+'"></div>');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
|
||||
String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),k=0;k=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,k);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection();
|
||||
this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){e(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
|
||||
if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
|
||||
d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=
|
||||
this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
|
||||
this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis];if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
|
||||
b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;
|
||||
f={width:c.size.width-(f?0:c.sizeDiff.width),height:c.size.height-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f,{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
|
||||
b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(l(b.left))this.position.left=b.left;if(l(b.top))this.position.top=b.top;if(l(b.height))this.size.height=b.height;if(l(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top=
|
||||
a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,d=l(b.width)&&a.maxWidth&&a.maxWidth<b.width,f=l(b.height)&&a.maxHeight&&a.maxHeight<b.height,g=l(b.width)&&a.minWidth&&a.minWidth>b.width,h=l(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
|
||||
k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minWidth;if(d&&k)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var d=[c.css("borderTopWidth"),
|
||||
c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],f=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=e.map(d,function(g,h){g=parseInt(g,10)||0;h=parseInt(f[h],10)||0;return g+h})}e.browser.msie&&(e(b).is(":hidden")||e(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
|
||||
this.element.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
|
||||
a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,
|
||||
arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,
|
||||
{version:"1.8.4"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,
|
||||
function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=
|
||||
(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=
|
||||
false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-
|
||||
a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",
|
||||
b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top",
|
||||
"Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset;var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,
|
||||
f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left:a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=
|
||||
a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top-d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+
|
||||
a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition,f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&
|
||||
e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",
|
||||
height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=
|
||||
d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
|
||||
;
|
480
src/Calendar.js
Normal file
|
@ -0,0 +1,480 @@
|
|||
|
||||
|
||||
function Calendar(element, options, eventSources) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.options = options;
|
||||
t.render = render;
|
||||
t.destroy = destroy;
|
||||
t.changeView = changeView;
|
||||
t.select = select;
|
||||
t.unselect = unselect;
|
||||
t.rerenderEvents = rerenderEvents; // todo: seems liks an EventManager thing
|
||||
t.prev = prev;
|
||||
t.next = next;
|
||||
t.prevYear = prevYear;
|
||||
t.nextYear = nextYear;
|
||||
t.today = today;
|
||||
t.gotoDate = gotoDate;
|
||||
t.incrementDate = incrementDate;
|
||||
t.formatDate = function(format, date) { return formatDate(format, date, options) };
|
||||
t.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) };
|
||||
t.getDate = getDate;
|
||||
t.getView = getView;
|
||||
t.option = option;
|
||||
t.trigger = trigger;
|
||||
|
||||
|
||||
// imports
|
||||
EventManager.call(t, options, eventSources);
|
||||
var fetchEvents = t.fetchEvents;
|
||||
var isFetchNeeded = t.isFetchNeeded;
|
||||
var clientEvents = t.clientEvents;
|
||||
|
||||
|
||||
// locals
|
||||
var _element = element[0];
|
||||
var header;
|
||||
var headerElement;
|
||||
var content;
|
||||
var tm; // for making theme classes
|
||||
var currentView;
|
||||
var viewInstances = {};
|
||||
var elementOuterWidth;
|
||||
var suggestedViewHeight;
|
||||
var absoluteViewElement;
|
||||
var resizeUID = 0;
|
||||
var ignoreWindowResize = 0;
|
||||
var date = new Date();
|
||||
|
||||
|
||||
|
||||
/* Main Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
setYMD(date, options.year, options.month, options.date);
|
||||
|
||||
|
||||
function render(inc) {
|
||||
if (!content) {
|
||||
initialRender();
|
||||
}else{
|
||||
calcSize();
|
||||
sizesDirty();
|
||||
eventsDirty();
|
||||
renderView(inc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initialRender() {
|
||||
tm = options.theme ? 'ui' : 'fc';
|
||||
element.addClass('fc');
|
||||
if (options.isRTL) {
|
||||
element.addClass('fc-rtl');
|
||||
}
|
||||
if (options.theme) {
|
||||
element.addClass('ui-widget');
|
||||
}
|
||||
content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>")
|
||||
.prependTo(element);
|
||||
header = new Header(t, options);
|
||||
headerElement = header.render();
|
||||
if (headerElement) {
|
||||
element.prepend(headerElement);
|
||||
}
|
||||
changeView(options.defaultView);
|
||||
$(window).resize(windowResize);
|
||||
// needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize
|
||||
if (!bodyVisible()) {
|
||||
lateRender();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// called when we know the calendar couldn't be rendered when it was initialized,
|
||||
// but we think it's ready now
|
||||
function lateRender() {
|
||||
setTimeout(function() { // IE7 needs this so dimensions are calculated correctly
|
||||
if (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once
|
||||
renderView();
|
||||
}
|
||||
},0);
|
||||
}
|
||||
|
||||
|
||||
function destroy() {
|
||||
$(window).unbind('resize', windowResize);
|
||||
header.destroy();
|
||||
content.remove();
|
||||
element.removeClass('fc fc-rtl fc-ui-widget');
|
||||
}
|
||||
|
||||
|
||||
|
||||
function elementVisible() {
|
||||
return _element.offsetWidth !== 0;
|
||||
}
|
||||
|
||||
|
||||
function bodyVisible() {
|
||||
return $('body')[0].offsetWidth !== 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* View Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function changeView(newViewName) {
|
||||
if (!currentView || newViewName != currentView.name) {
|
||||
ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
|
||||
|
||||
unselect();
|
||||
|
||||
var oldView = currentView;
|
||||
var newViewElement;
|
||||
|
||||
if (oldView) {
|
||||
if (oldView.eventsChanged) {
|
||||
eventsDirty();
|
||||
oldView.eventDirty = oldView.eventsChanged = false;
|
||||
}
|
||||
(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
|
||||
setMinHeight(content, content.height());
|
||||
oldView.element.hide();
|
||||
}else{
|
||||
setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated
|
||||
}
|
||||
content.css('overflow', 'hidden');
|
||||
|
||||
currentView = viewInstances[newViewName];
|
||||
if (currentView) {
|
||||
currentView.element.show();
|
||||
}else{
|
||||
currentView = viewInstances[newViewName] = new fcViews[newViewName](
|
||||
newViewElement = absoluteViewElement =
|
||||
$("<div class='fc-view fc-view-" + newViewName + "' style='position:absolute'/>")
|
||||
.appendTo(content),
|
||||
t // the calendar object
|
||||
);
|
||||
}
|
||||
|
||||
if (oldView) {
|
||||
header.deactivateButton(oldView.name);
|
||||
}
|
||||
header.activateButton(newViewName);
|
||||
|
||||
renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null
|
||||
|
||||
content.css('overflow', '');
|
||||
if (oldView) {
|
||||
setMinHeight(content, 1);
|
||||
}
|
||||
|
||||
if (!newViewElement) {
|
||||
(currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera)
|
||||
}
|
||||
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function renderView(inc) {
|
||||
if (elementVisible()) {
|
||||
ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached
|
||||
|
||||
unselect();
|
||||
|
||||
if (suggestedViewHeight === undefined) {
|
||||
calcSize();
|
||||
}
|
||||
|
||||
if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
|
||||
currentView.render(date, inc || 0); // responsible for clearing events
|
||||
setSize(true);
|
||||
if (!options.lazyFetching || isFetchNeeded()) {
|
||||
fetchAndRenderEvents();
|
||||
}else{
|
||||
currentView.renderEvents(clientEvents()); // don't refetch
|
||||
}
|
||||
}
|
||||
else if (currentView.sizeDirty || currentView.eventsDirty || !options.lazyFetching) {
|
||||
currentView.clearEvents();
|
||||
if (currentView.sizeDirty) {
|
||||
setSize();
|
||||
}
|
||||
if (!options.lazyFetching || isFetchNeeded()) {
|
||||
fetchAndRenderEvents();
|
||||
}else{
|
||||
currentView.renderEvents(clientEvents()); // don't refetch
|
||||
}
|
||||
}
|
||||
elementOuterWidth = element.outerWidth();
|
||||
currentView.sizeDirty = false;
|
||||
currentView.eventsDirty = false;
|
||||
|
||||
header.updateTitle(currentView.title);
|
||||
var today = new Date();
|
||||
if (today >= currentView.start && today < currentView.end) {
|
||||
header.disableButton('today');
|
||||
}else{
|
||||
header.enableButton('today');
|
||||
}
|
||||
|
||||
ignoreWindowResize--;
|
||||
currentView.trigger('viewDisplay', _element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Resizing
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function calcSize() {
|
||||
if (options.contentHeight) {
|
||||
suggestedViewHeight = options.contentHeight;
|
||||
}
|
||||
else if (options.height) {
|
||||
suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content[0]);
|
||||
}
|
||||
else {
|
||||
suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setSize(dateChanged) { // todo: dateChanged?
|
||||
ignoreWindowResize++;
|
||||
currentView.setHeight(suggestedViewHeight, dateChanged);
|
||||
if (absoluteViewElement) {
|
||||
absoluteViewElement.css('position', 'relative');
|
||||
absoluteViewElement = null;
|
||||
}
|
||||
currentView.setWidth(content.width(), dateChanged);
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
|
||||
|
||||
function windowResize() {
|
||||
if (!ignoreWindowResize) {
|
||||
if (currentView.start) { // view has already been rendered
|
||||
var uid = ++resizeUID;
|
||||
setTimeout(function() { // add a delay
|
||||
if (uid == resizeUID && !ignoreWindowResize && elementVisible()) {
|
||||
if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {
|
||||
ignoreWindowResize++; // in case the windowResize callback changes the height
|
||||
sizeChanged();
|
||||
currentView.trigger('windowResize', _element);
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
}else{
|
||||
// calendar must have been initialized in a 0x0 iframe that has just been resized
|
||||
lateRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// called when we know the element size has changed
|
||||
function sizeChanged() {
|
||||
sizesDirty();
|
||||
if (elementVisible()) {
|
||||
calcSize();
|
||||
setSize();
|
||||
unselect();
|
||||
currentView.rerenderEvents();
|
||||
currentView.sizeDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// marks other views' sizes as dirty
|
||||
function sizesDirty() {
|
||||
$.each(viewInstances, function(i, inst) {
|
||||
inst.sizeDirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// called when any event objects have been added/removed/changed, rerenders
|
||||
function rerenderEvents() {
|
||||
eventsDirty();
|
||||
if (elementVisible()) {
|
||||
currentView.clearEvents();
|
||||
currentView.renderEvents(clientEvents());
|
||||
currentView.eventsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// marks every views' events as dirty
|
||||
function eventsDirty() {
|
||||
$.each(viewInstances, function(i, inst) {
|
||||
inst.eventsDirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// for convenience
|
||||
function fetchAndRenderEvents() {
|
||||
fetchEvents(function(events) {
|
||||
currentView.renderEvents(events); // maintain `this` in view
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Selection
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function select(start, end, allDay) {
|
||||
currentView.select(start, end, allDay===undefined ? true : allDay);
|
||||
}
|
||||
|
||||
|
||||
function unselect() { // safe to be called before renderView
|
||||
if (currentView) {
|
||||
currentView.unselect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Date
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function prev() {
|
||||
renderView(-1);
|
||||
}
|
||||
|
||||
|
||||
function next() {
|
||||
renderView(1);
|
||||
}
|
||||
|
||||
|
||||
function prevYear() {
|
||||
addYears(date, -1);
|
||||
renderView();
|
||||
}
|
||||
|
||||
|
||||
function nextYear() {
|
||||
addYears(date, 1);
|
||||
renderView();
|
||||
}
|
||||
|
||||
|
||||
function today() {
|
||||
date = new Date();
|
||||
renderView();
|
||||
}
|
||||
|
||||
|
||||
function gotoDate(year, month, dateOfMonth) {
|
||||
if (year instanceof Date) {
|
||||
date = cloneDate(year); // provided 1 argument, a Date
|
||||
}else{
|
||||
setYMD(date, year, month, dateOfMonth);
|
||||
}
|
||||
renderView();
|
||||
}
|
||||
|
||||
|
||||
function incrementDate(years, months, days) {
|
||||
if (years !== undefined) {
|
||||
addYears(date, years);
|
||||
}
|
||||
if (months !== undefined) {
|
||||
addMonths(date, months);
|
||||
}
|
||||
if (days !== undefined) {
|
||||
addDays(date, days);
|
||||
}
|
||||
renderView();
|
||||
}
|
||||
|
||||
|
||||
function getDate() {
|
||||
return cloneDate(date);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Misc
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function getView() {
|
||||
return currentView;
|
||||
}
|
||||
|
||||
|
||||
function option(name, value) {
|
||||
if (value === undefined) {
|
||||
return options[name];
|
||||
}
|
||||
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
||||
options[name] = value;
|
||||
sizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function trigger(name, thisObj) {
|
||||
if (options[name]) {
|
||||
return options[name].apply(
|
||||
thisObj || _element,
|
||||
Array.prototype.slice.call(arguments, 2)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* External Dragging
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
var _dragElement;
|
||||
|
||||
if (options.droppable) {
|
||||
$(document)
|
||||
.bind('dragstart', function(ev, ui) {
|
||||
var _e = ev.target;
|
||||
var e = $(_e);
|
||||
if (!e.parents('.fc').length) { // not already inside a calendar
|
||||
var accept = options.dropAccept;
|
||||
if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) {
|
||||
_dragElement = _e;
|
||||
currentView.dragStart(_dragElement, ev, ui);
|
||||
}
|
||||
}
|
||||
})
|
||||
.bind('dragstop', function(ev, ui) {
|
||||
if (_dragElement) {
|
||||
currentView.dragStop(_dragElement, ev, ui);
|
||||
_dragElement = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
288
src/EventManager.js
Normal file
|
@ -0,0 +1,288 @@
|
|||
|
||||
var eventGUID = 1;
|
||||
|
||||
function EventManager(options, eventSources) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.fetchEvents = fetchEvents;
|
||||
t.refetchEvents = refetchEvents;
|
||||
t.isFetchNeeded = isFetchNeeded;
|
||||
t.addEventSource = addEventSource;
|
||||
t.removeEventSource = removeEventSource;
|
||||
t.updateEvent = updateEvent;
|
||||
t.renderEvent = renderEvent;
|
||||
t.removeEvents = removeEvents;
|
||||
t.clientEvents = clientEvents;
|
||||
t.normalizeEvent = normalizeEvent;
|
||||
|
||||
|
||||
// imports
|
||||
var getDate = t.getDate;
|
||||
var getView = t.getView;
|
||||
var trigger = t.trigger;
|
||||
var rerenderEvents = t.rerenderEvents;
|
||||
|
||||
|
||||
// locals
|
||||
var eventStart, eventEnd;
|
||||
var events = [];
|
||||
var loadingLevel = 0;
|
||||
|
||||
|
||||
|
||||
/* Sources
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
eventSources.unshift([]); // first event source reserved for 'sticky' events
|
||||
|
||||
|
||||
function addEventSource(source) {
|
||||
eventSources.push(source);
|
||||
fetchEventSource(source, rerenderEvents);
|
||||
}
|
||||
|
||||
|
||||
function removeEventSource(source) {
|
||||
eventSources = $.grep(eventSources, function(src) {
|
||||
return src != source;
|
||||
});
|
||||
// remove all client events from that source
|
||||
events = $.grep(events, function(e) {
|
||||
return e.source != source;
|
||||
});
|
||||
rerenderEvents();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Fetching
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// Fetch from ALL sources. Clear 'events' array and populate
|
||||
function fetchEvents(callback) {
|
||||
var view = getView();
|
||||
events = [];
|
||||
eventStart = cloneDate(view.visStart);
|
||||
eventEnd = cloneDate(view.visEnd);
|
||||
var queued = eventSources.length,
|
||||
sourceDone = function() {
|
||||
if (!--queued) {
|
||||
if (callback) {
|
||||
callback(events);
|
||||
}
|
||||
}
|
||||
}, i=0;
|
||||
for (; i<eventSources.length; i++) {
|
||||
fetchEventSource(eventSources[i], sourceDone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fetch from a particular source. Append to the 'events' array
|
||||
function fetchEventSource(src, callback) {
|
||||
var prevView = getView(),
|
||||
prevDate = getDate(),
|
||||
reportEvents = function(a) {
|
||||
if (prevView == getView() && +prevDate == +getDate() && // protects from fast switching
|
||||
$.inArray(src, eventSources) != -1) { // makes sure source hasn't been removed
|
||||
for (var i=0; i<a.length; i++) {
|
||||
normalizeEvent(a[i]);
|
||||
a[i].source = src;
|
||||
}
|
||||
events = events.concat(a);
|
||||
if (callback) {
|
||||
callback(a);
|
||||
}
|
||||
}
|
||||
},
|
||||
reportEventsAndPop = function(a) {
|
||||
reportEvents(a);
|
||||
popLoading();
|
||||
};
|
||||
if (typeof src == 'string') {
|
||||
var params = {};
|
||||
params[options.startParam] = Math.round(eventStart.getTime() / 1000);
|
||||
params[options.endParam] = Math.round(eventEnd.getTime() / 1000);
|
||||
if (options.cacheParam) {
|
||||
params[options.cacheParam] = (new Date()).getTime(); // TODO: deprecate cacheParam
|
||||
}
|
||||
pushLoading();
|
||||
// TODO: respect cache param in ajaxSetup
|
||||
$.ajax({
|
||||
url: src,
|
||||
dataType: 'json',
|
||||
data: params,
|
||||
cache: options.cacheParam || false, // don't let jquery prevent caching if cacheParam is being used
|
||||
success: reportEventsAndPop
|
||||
});
|
||||
}
|
||||
else if ($.isFunction(src)) {
|
||||
pushLoading();
|
||||
src(cloneDate(eventStart), cloneDate(eventEnd), reportEventsAndPop);
|
||||
}
|
||||
else {
|
||||
reportEvents(src); // src is an array
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function refetchEvents() {
|
||||
fetchEvents(rerenderEvents);
|
||||
}
|
||||
|
||||
|
||||
function isFetchNeeded() {
|
||||
var view = getView();
|
||||
return !eventStart || view.visStart < eventStart || view.visEnd > eventEnd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Manipulation
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function updateEvent(event) { // update an existing event
|
||||
var i, len = events.length, e,
|
||||
defaultEventEnd = getView().defaultEventEnd,
|
||||
startDelta = event.start - event._start,
|
||||
endDelta = event.end ?
|
||||
(event.end - (event._end || defaultEventEnd(event))) // event._end would be null if event.end
|
||||
: 0; // was null and event was just resized
|
||||
for (i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
if (e._id == event._id && e != event) {
|
||||
e.start = new Date(+e.start + startDelta);
|
||||
if (event.end) {
|
||||
if (e.end) {
|
||||
e.end = new Date(+e.end + endDelta);
|
||||
}else{
|
||||
e.end = new Date(+defaultEventEnd(e) + endDelta);
|
||||
}
|
||||
}else{
|
||||
e.end = null;
|
||||
}
|
||||
e.title = event.title;
|
||||
e.url = event.url;
|
||||
e.allDay = event.allDay;
|
||||
e.className = event.className;
|
||||
e.editable = event.editable;
|
||||
normalizeEvent(e);
|
||||
}
|
||||
}
|
||||
normalizeEvent(event);
|
||||
rerenderEvents();
|
||||
}
|
||||
|
||||
|
||||
function renderEvent(event, stick) { // render a new event
|
||||
normalizeEvent(event);
|
||||
if (!event.source) {
|
||||
if (stick) {
|
||||
(event.source = eventSources[0]).push(event);
|
||||
}
|
||||
events.push(event);
|
||||
}
|
||||
rerenderEvents();
|
||||
}
|
||||
|
||||
|
||||
function removeEvents(filter) {
|
||||
if (!filter) { // remove all
|
||||
events = [];
|
||||
// clear all array sources
|
||||
for (var i=0; i<eventSources.length; i++) {
|
||||
if (typeof eventSources[i] == 'object') {
|
||||
eventSources[i] = [];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (!$.isFunction(filter)) { // an event ID
|
||||
var id = filter + '';
|
||||
filter = function(e) {
|
||||
return e._id == id;
|
||||
};
|
||||
}
|
||||
events = $.grep(events, filter, true);
|
||||
// remove events from array sources
|
||||
for (var i=0; i<eventSources.length; i++) {
|
||||
if (typeof eventSources[i] == 'object') {
|
||||
eventSources[i] = $.grep(eventSources[i], filter, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
rerenderEvents();
|
||||
}
|
||||
|
||||
|
||||
function clientEvents(filter) {
|
||||
if ($.isFunction(filter)) {
|
||||
return $.grep(events, filter);
|
||||
}
|
||||
else if (filter) { // an event ID
|
||||
filter += '';
|
||||
return $.grep(events, function(e) {
|
||||
return e._id == filter;
|
||||
});
|
||||
}
|
||||
return events; // else, return all
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Loading State
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function pushLoading() {
|
||||
if (!loadingLevel++) {
|
||||
trigger('loading', null, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function popLoading() {
|
||||
if (!--loadingLevel) {
|
||||
trigger('loading', null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Normalization
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function normalizeEvent(event) {
|
||||
event._id = event._id || (event.id === undefined ? '_fc' + eventGUID++ : event.id + '');
|
||||
if (event.date) {
|
||||
if (!event.start) {
|
||||
event.start = event.date;
|
||||
}
|
||||
delete event.date;
|
||||
}
|
||||
event._start = cloneDate(event.start = parseDate(event.start));
|
||||
event.end = parseDate(event.end);
|
||||
if (event.end && event.end <= event.start) {
|
||||
event.end = null;
|
||||
}
|
||||
event._end = event.end ? cloneDate(event.end) : null;
|
||||
if (event.allDay === undefined) {
|
||||
event.allDay = options.allDayDefault;
|
||||
}
|
||||
if (event.className) {
|
||||
if (typeof event.className == 'string') {
|
||||
event.className = event.className.split(/\s+/);
|
||||
}
|
||||
}else{
|
||||
event.className = [];
|
||||
}
|
||||
// TODO: if there is no start date, return false to indicate an invalid event
|
||||
}
|
||||
|
||||
|
||||
}
|
164
src/Header.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
|
||||
function Header(calendar, options) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
t.destroy = destroy;
|
||||
t.updateTitle = updateTitle;
|
||||
t.activateButton = activateButton;
|
||||
t.deactivateButton = deactivateButton;
|
||||
t.disableButton = disableButton;
|
||||
t.enableButton = enableButton;
|
||||
|
||||
|
||||
// locals
|
||||
var element = $([]);
|
||||
var tm;
|
||||
|
||||
|
||||
|
||||
function render() {
|
||||
tm = options.theme ? 'ui' : 'fc';
|
||||
var sections = options.header;
|
||||
if (sections) {
|
||||
element = $("<table class='fc-header'/>")
|
||||
.append($("<tr/>")
|
||||
.append($("<td class='fc-header-left'/>")
|
||||
.append(renderSection(sections.left)))
|
||||
.append($("<td class='fc-header-center'/>")
|
||||
.append(renderSection(sections.center)))
|
||||
.append($("<td class='fc-header-right'/>")
|
||||
.append(renderSection(sections.right))));
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function destroy() {
|
||||
element.remove();
|
||||
}
|
||||
|
||||
|
||||
function renderSection(buttonStr) {
|
||||
if (buttonStr) {
|
||||
var tr = $("<tr/>");
|
||||
$.each(buttonStr.split(' '), function(i) {
|
||||
if (i > 0) {
|
||||
tr.append("<td><span class='fc-header-space'/></td>");
|
||||
}
|
||||
var prevButton;
|
||||
$.each(this.split(','), function(j, buttonName) {
|
||||
if (buttonName == 'title') {
|
||||
tr.append("<td><h2 class='fc-header-title'> </h2></td>");
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-corner-right');
|
||||
}
|
||||
prevButton = null;
|
||||
}else{
|
||||
var buttonClick;
|
||||
if (calendar[buttonName]) {
|
||||
buttonClick = calendar[buttonName]; // calendar method
|
||||
}
|
||||
else if (fcViews[buttonName]) {
|
||||
buttonClick = function() {
|
||||
button.removeClass(tm + '-state-hover'); // forget why
|
||||
calendar.changeView(buttonName);
|
||||
};
|
||||
}
|
||||
if (buttonClick) {
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-no-right');
|
||||
}
|
||||
var button;
|
||||
var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null;
|
||||
var text = smartProperty(options.buttonText, buttonName);
|
||||
if (icon) {
|
||||
button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
|
||||
"<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
|
||||
}
|
||||
else if (text) {
|
||||
button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
|
||||
"<a><span>" + text + "</span></a></div>");
|
||||
}
|
||||
if (button) {
|
||||
button
|
||||
.click(function() {
|
||||
if (!button.hasClass(tm + '-state-disabled')) {
|
||||
buttonClick();
|
||||
}
|
||||
})
|
||||
.mousedown(function() {
|
||||
button
|
||||
.not('.' + tm + '-state-active')
|
||||
.not('.' + tm + '-state-disabled')
|
||||
.addClass(tm + '-state-down');
|
||||
})
|
||||
.mouseup(function() {
|
||||
button.removeClass(tm + '-state-down');
|
||||
})
|
||||
.hover(
|
||||
function() {
|
||||
button
|
||||
.not('.' + tm + '-state-active')
|
||||
.not('.' + tm + '-state-disabled')
|
||||
.addClass(tm + '-state-hover');
|
||||
},
|
||||
function() {
|
||||
button
|
||||
.removeClass(tm + '-state-hover')
|
||||
.removeClass(tm + '-state-down');
|
||||
}
|
||||
)
|
||||
.appendTo($("<td/>").appendTo(tr));
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-no-right');
|
||||
}else{
|
||||
button.addClass(tm + '-corner-left');
|
||||
}
|
||||
prevButton = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-corner-right');
|
||||
}
|
||||
});
|
||||
return $("<table/>").append(tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateTitle(html) {
|
||||
element.find('h2.fc-header-title')
|
||||
.html(html);
|
||||
}
|
||||
|
||||
|
||||
function activateButton(buttonName) {
|
||||
element.find('div.fc-button-' + buttonName)
|
||||
.addClass(tm + '-state-active');
|
||||
}
|
||||
|
||||
|
||||
function deactivateButton(buttonName) {
|
||||
element.find('div.fc-button-' + buttonName)
|
||||
.removeClass(tm + '-state-active');
|
||||
}
|
||||
|
||||
|
||||
function disableButton(buttonName) {
|
||||
element.find('div.fc-button-' + buttonName)
|
||||
.addClass(tm + '-state-disabled');
|
||||
}
|
||||
|
||||
|
||||
function enableButton(buttonName) {
|
||||
element.find('div.fc-button-' + buttonName)
|
||||
.removeClass(tm + '-state-disabled');
|
||||
}
|
||||
|
||||
|
||||
}
|
132
src/_loader.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
(function() {
|
||||
|
||||
var JQUERY = 'jquery-1.4.2.min.js';
|
||||
var JQUERY_UI = 'jquery-ui-1.8.4.custom.min.js';
|
||||
var JQUERY_LEGACY = 'jquery-1.3.2.min.js';
|
||||
var JQUERY_UI_LEGACY = 'jquery-ui-1.7.3.custom.min.js';
|
||||
|
||||
var qs = window.location.href.match(/(\?.*)?$/)[0];
|
||||
var legacy = qs.indexOf('legacy') != -1;
|
||||
var noui = qs.indexOf('noui') != -1;
|
||||
var debug;
|
||||
var prefix;
|
||||
var tags;
|
||||
|
||||
|
||||
startload();
|
||||
|
||||
css('main.css');
|
||||
css('common/common.css');
|
||||
css('basic/basic.css');
|
||||
css('agenda/agenda.css');
|
||||
|
||||
if (!legacy) {
|
||||
jslib('../lib/' + JQUERY);
|
||||
if (!noui) {
|
||||
jslib('../lib/' + JQUERY_UI);
|
||||
}
|
||||
}else{
|
||||
jslib('../lib/' + JQUERY_LEGACY);
|
||||
if (!noui) {
|
||||
jslib('../lib/' + JQUERY_UI_LEGACY);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug && (!window.console || !window.console.log)) {
|
||||
jslib('../tests/lib/firebug-lite/firebug-lite-compressed.js');
|
||||
}
|
||||
|
||||
js('defaults.js');
|
||||
js('main.js');
|
||||
js('Calendar.js');
|
||||
js('Header.js');
|
||||
js('EventManager.js');
|
||||
|
||||
js('basic/MonthView.js');
|
||||
js('basic/BasicWeekView.js');
|
||||
js('basic/BasicDayView.js');
|
||||
js('basic/BasicView.js');
|
||||
js('basic/BasicEventRenderer.js');
|
||||
|
||||
js('agenda/AgendaWeekView.js');
|
||||
js('agenda/AgendaDayView.js');
|
||||
js('agenda/AgendaView.js');
|
||||
js('agenda/AgendaEventRenderer.js');
|
||||
|
||||
js('common/View.js');
|
||||
js('common/DayEventRenderer.js');
|
||||
js('common/SelectionManager.js');
|
||||
js('common/OverlayManager.js');
|
||||
js('common/CoordinateGrid.js');
|
||||
js('common/HoverListener.js');
|
||||
js('common/HorizontalPositionCache.js');
|
||||
js('common/date.js');
|
||||
js('common/util.js');
|
||||
|
||||
endload();
|
||||
|
||||
|
||||
if (debug) {
|
||||
window.onload = function() {
|
||||
$('body').append(
|
||||
"<form style='position:absolute;top:0;right:0;text-align:right;font-size:10px;color:#666'>" +
|
||||
"<label for='legacy'>legacy</label> " +
|
||||
"<input type='checkbox' id='legacy' name='legacy'" + (legacy ? " checked='checked'" : '') +
|
||||
" style='vertical-align:middle' onclick='$(this).parent().submit()' />" +
|
||||
"<br />" +
|
||||
"<label for='ui'>no jquery ui</label> " +
|
||||
"<input type='checkbox' id='ui' name='noui'" + (noui ? " checked='checked'" : '') +
|
||||
" style='vertical-align:middle' onclick='$(this).parent().submit()' />" +
|
||||
"</form>"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
window.startload = startload;
|
||||
window.endload = endload;
|
||||
window.css = css;
|
||||
window.js = js;
|
||||
window.jslib = jslib;
|
||||
|
||||
|
||||
function startload() {
|
||||
debug = false;
|
||||
prefix = '';
|
||||
tags = [];
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i=0, script; script=scripts[i++];) {
|
||||
if (!script._checked) {
|
||||
script._checked = true;
|
||||
var m = (script.getAttribute('src') || '').match(/^(.*)_loader\.js(\?.*)?$/);
|
||||
if (m) {
|
||||
prefix = m[1];
|
||||
debug = (m[2] || '').indexOf('debug') != -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function endload() {
|
||||
document.write(tags.join("\n"));
|
||||
}
|
||||
|
||||
|
||||
function css(file) {
|
||||
tags.push("<link rel='stylesheet' type='text/css' href='" + prefix + file + "' />");
|
||||
}
|
||||
|
||||
|
||||
function js(file) {
|
||||
tags.push("<script type='text/javascript' src='" + prefix + file + "'></script>");
|
||||
}
|
||||
|
||||
|
||||
function jslib(file) {
|
||||
js(file);
|
||||
}
|
||||
|
||||
|
||||
})();
|
1249
src/agenda.js
36
src/agenda/AgendaDayView.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
fcViews.agendaDay = AgendaDayView;
|
||||
|
||||
function AgendaDayView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
|
||||
|
||||
// imports
|
||||
AgendaView.call(t, element, calendar, 'agendaDay');
|
||||
var opt = t.opt;
|
||||
var renderAgenda = t.renderAgenda;
|
||||
var formatDate = calendar.formatDate;
|
||||
|
||||
|
||||
|
||||
function render(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta);
|
||||
if (!opt('weekends')) {
|
||||
skipWeekend(date, delta < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
var start = cloneDate(date, true);
|
||||
var end = addDays(cloneDate(start), 1);
|
||||
t.title = formatDate(date, opt('titleFormat'));
|
||||
t.start = t.visStart = start;
|
||||
t.end = t.visEnd = end;
|
||||
renderAgenda(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
595
src/agenda/AgendaEventRenderer.js
Normal file
|
@ -0,0 +1,595 @@
|
|||
|
||||
function AgendaEventRenderer() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderEvents = renderEvents;
|
||||
t.rerenderEvents = rerenderEvents;
|
||||
t.clearEvents = clearEvents;
|
||||
t.slotSegHtml = slotSegHtml;
|
||||
t.bindDaySeg = bindDaySeg;
|
||||
|
||||
|
||||
// imports
|
||||
DayEventRenderer.call(t);
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var eventEnd = t.eventEnd;
|
||||
var reportEvents = t.reportEvents;
|
||||
var clearEventData = t.clearEventData;
|
||||
var eventElementHandlers = t.eventElementHandlers;
|
||||
var setHeight = t.setHeight;
|
||||
var getDaySegmentContainer = t.getDaySegmentContainer;
|
||||
var getSlotSegmentContainer = t.getSlotSegmentContainer;
|
||||
var getHoverListener = t.getHoverListener;
|
||||
var getMaxMinute = t.getMaxMinute;
|
||||
var getMinMinute = t.getMinMinute;
|
||||
var timePosition = t.timePosition;
|
||||
var colContentLeft = t.colContentLeft;
|
||||
var colContentRight = t.colContentRight;
|
||||
var renderDaySegs = t.renderDaySegs;
|
||||
var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture
|
||||
var getColCnt = t.getColCnt;
|
||||
var getColWidth = t.getColWidth;
|
||||
var getSlotHeight = t.getSlotHeight;
|
||||
var getBodyContent = t.getBodyContent;
|
||||
var reportEventElement = t.reportEventElement;
|
||||
var showEvents = t.showEvents;
|
||||
var hideEvents = t.hideEvents;
|
||||
var eventDrop = t.eventDrop;
|
||||
var eventResize = t.eventResize;
|
||||
var renderDayOverlay = t.renderDayOverlay;
|
||||
var clearOverlays = t.clearOverlays;
|
||||
var calendar = t.calendar;
|
||||
var formatDate = calendar.formatDate;
|
||||
var formatDates = calendar.formatDates;
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
var cachedEvents = [];
|
||||
|
||||
|
||||
function renderEvents(events, modifiedEventId) {
|
||||
reportEvents(cachedEvents = events);
|
||||
var i, len=events.length,
|
||||
dayEvents=[],
|
||||
slotEvents=[];
|
||||
for (i=0; i<len; i++) {
|
||||
if (events[i].allDay) {
|
||||
dayEvents.push(events[i]);
|
||||
}else{
|
||||
slotEvents.push(events[i]);
|
||||
}
|
||||
}
|
||||
if (opt('allDaySlot')) {
|
||||
renderDaySegs(compileDaySegs(dayEvents), modifiedEventId);
|
||||
setHeight(); // no params means set to viewHeight
|
||||
}
|
||||
renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
|
||||
}
|
||||
|
||||
|
||||
function rerenderEvents(modifiedEventId) {
|
||||
clearEvents();
|
||||
renderEvents(cachedEvents, modifiedEventId);
|
||||
}
|
||||
|
||||
|
||||
function clearEvents() {
|
||||
clearEventData();
|
||||
getDaySegmentContainer().empty();
|
||||
getSlotSegmentContainer().empty();
|
||||
}
|
||||
|
||||
|
||||
function compileDaySegs(events) {
|
||||
var levels = stackSegs(sliceSegs(events, $.map(events, exclEndDay), t.visStart, t.visEnd)),
|
||||
i, levelCnt=levels.length, level,
|
||||
j, seg,
|
||||
segs=[];
|
||||
for (i=0; i<levelCnt; i++) {
|
||||
level = levels[i];
|
||||
for (j=0; j<level.length; j++) {
|
||||
seg = level[j];
|
||||
seg.row = 0;
|
||||
seg.level = i;
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
||||
function compileSlotSegs(events) {
|
||||
var colCnt = getColCnt(),
|
||||
minMinute = getMinMinute(),
|
||||
maxMinute = getMaxMinute(),
|
||||
d = addMinutes(cloneDate(t.visStart), minMinute),
|
||||
visEventEnds = $.map(events, slotEventEnd),
|
||||
i, col,
|
||||
j, level,
|
||||
k, seg,
|
||||
segs=[];
|
||||
for (i=0; i<colCnt; i++) {
|
||||
col = stackSegs(sliceSegs(events, visEventEnds, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
||||
countForwardSegs(col);
|
||||
for (j=0; j<col.length; j++) {
|
||||
level = col[j];
|
||||
for (k=0; k<level.length; k++) {
|
||||
seg = level[k];
|
||||
seg.col = i;
|
||||
seg.level = j;
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
addDays(d, 1, true);
|
||||
}
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
||||
function slotEventEnd(event) {
|
||||
if (event.end) {
|
||||
return cloneDate(event.end);
|
||||
}else{
|
||||
return addMinutes(cloneDate(event.start), opt('defaultEventMinutes'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// renders events in the 'time slots' at the bottom
|
||||
|
||||
function renderSlotSegs(segs, modifiedEventId) {
|
||||
|
||||
var i, segCnt=segs.length, seg,
|
||||
event,
|
||||
className,
|
||||
top, bottom,
|
||||
colI, levelI, forward,
|
||||
leftmost,
|
||||
availWidth,
|
||||
outerWidth,
|
||||
left,
|
||||
html='',
|
||||
eventElements,
|
||||
eventElement,
|
||||
triggerRes,
|
||||
vsideCache={},
|
||||
hsideCache={},
|
||||
key, val,
|
||||
titleSpan,
|
||||
height,
|
||||
slotSegmentContainer = getSlotSegmentContainer(),
|
||||
rtl, dis, dit,
|
||||
colCnt = getColCnt();
|
||||
|
||||
if (rtl = opt('isRTL')) {
|
||||
dis = -1;
|
||||
dit = colCnt - 1;
|
||||
}else{
|
||||
dis = 1;
|
||||
dit = 0;
|
||||
}
|
||||
|
||||
// calculate position/dimensions, create html
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
event = seg.event;
|
||||
className = 'fc-event fc-event-vert ';
|
||||
if (seg.isStart) {
|
||||
className += 'fc-corner-top ';
|
||||
}
|
||||
if (seg.isEnd) {
|
||||
className += 'fc-corner-bottom ';
|
||||
}
|
||||
top = timePosition(seg.start, seg.start);
|
||||
bottom = timePosition(seg.start, seg.end);
|
||||
colI = seg.col;
|
||||
levelI = seg.level;
|
||||
forward = seg.forward || 0;
|
||||
leftmost = colContentLeft(colI*dis + dit);
|
||||
availWidth = colContentRight(colI*dis + dit) - leftmost;
|
||||
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
||||
if (levelI) {
|
||||
// indented and thin
|
||||
outerWidth = availWidth / (levelI + forward + 1);
|
||||
}else{
|
||||
if (forward) {
|
||||
// moderately wide, aligned left still
|
||||
outerWidth = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
||||
}else{
|
||||
// can be entire width, aligned left
|
||||
outerWidth = availWidth;
|
||||
}
|
||||
}
|
||||
left = leftmost + // leftmost possible
|
||||
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
||||
* dis + (rtl ? availWidth - outerWidth : 0); // rtl
|
||||
seg.top = top;
|
||||
seg.left = left;
|
||||
seg.outerWidth = outerWidth;
|
||||
seg.outerHeight = bottom - top;
|
||||
html += slotSegHtml(event, seg, className);
|
||||
}
|
||||
slotSegmentContainer[0].innerHTML = html; // faster than html()
|
||||
eventElements = slotSegmentContainer.children();
|
||||
|
||||
// retrieve elements, run through eventRender callback, bind event handlers
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
event = seg.event;
|
||||
eventElement = $(eventElements[i]); // faster than eq()
|
||||
triggerRes = trigger('eventRender', event, event, eventElement);
|
||||
if (triggerRes === false) {
|
||||
eventElement.remove();
|
||||
}else{
|
||||
if (triggerRes && triggerRes !== true) {
|
||||
eventElement.remove();
|
||||
eventElement = $(triggerRes)
|
||||
.css({
|
||||
position: 'absolute',
|
||||
top: seg.top,
|
||||
left: seg.left
|
||||
})
|
||||
.appendTo(slotSegmentContainer);
|
||||
}
|
||||
seg.element = eventElement;
|
||||
if (event._id === modifiedEventId) {
|
||||
bindSlotSeg(event, eventElement, seg);
|
||||
}else{
|
||||
eventElement[0]._fci = i; // for lazySegBind
|
||||
}
|
||||
reportEventElement(event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
lazySegBind(slotSegmentContainer, segs, bindSlotSeg);
|
||||
|
||||
// record event sides and title positions
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
val = vsideCache[key = seg.key = cssKey(eventElement[0])];
|
||||
seg.vsides = val === undefined ? (vsideCache[key] = vsides(eventElement[0], true)) : val;
|
||||
val = hsideCache[key];
|
||||
seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
||||
titleSpan = eventElement.find('span.fc-event-title');
|
||||
if (titleSpan.length) {
|
||||
seg.titleTop = titleSpan[0].offsetTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set all positions/dimensions at once
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
||||
eventElement[0].style.height = (height = seg.outerHeight - seg.vsides) + 'px';
|
||||
event = seg.event;
|
||||
if (seg.titleTop !== undefined && height - seg.titleTop < 10) {
|
||||
// not enough room for title, put it in the time header
|
||||
eventElement.find('span.fc-event-time')
|
||||
.text(formatDate(event.start, opt('timeFormat')) + ' - ' + event.title);
|
||||
eventElement.find('span.fc-event-title')
|
||||
.remove();
|
||||
}
|
||||
trigger('eventAfterRender', event, event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function slotSegHtml(event, seg, className) {
|
||||
return "<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px'>" +
|
||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||
"<span class='fc-event-bg'></span>" +
|
||||
"<span class='fc-event-time'>" + htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + "</span>" +
|
||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||
"</a>" +
|
||||
((event.editable || event.editable === undefined && opt('editable')) && !opt('disableResizing') && $.fn.resizable ?
|
||||
"<div class='ui-resizable-handle ui-resizable-s'>=</div>"
|
||||
: '') +
|
||||
"</div>";
|
||||
}
|
||||
|
||||
|
||||
function bindDaySeg(event, eventElement, seg) {
|
||||
eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && opt('editable')) {
|
||||
draggableDayEvent(event, eventElement, seg.isStart);
|
||||
if (seg.isEnd) {
|
||||
resizableDayEvent(event, eventElement, getColWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function bindSlotSeg(event, eventElement, seg) {
|
||||
eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && opt('editable')) {
|
||||
var timeElement = eventElement.find('span.fc-event-time');
|
||||
draggableSlotEvent(event, eventElement, timeElement);
|
||||
if (seg.isEnd) {
|
||||
resizableSlotEvent(event, eventElement, timeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Dragging
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// when event starts out FULL-DAY
|
||||
|
||||
function draggableDayEvent(event, eventElement, isStart) {
|
||||
if (!opt('disableDragging') && eventElement.draggable) {
|
||||
var origWidth;
|
||||
var allDay=true;
|
||||
var dayDelta;
|
||||
var dis = opt('isRTL') ? -1 : 1;
|
||||
var hoverListener = getHoverListener();
|
||||
var colWidth = getColWidth();
|
||||
var slotHeight = getSlotHeight();
|
||||
var minMinute = getMinMinute();
|
||||
eventElement.draggable({
|
||||
zIndex: 9,
|
||||
opacity: opt('dragOpacity', 'month'), // use whatever the month view was using
|
||||
revertDuration: opt('dragRevertDuration'),
|
||||
start: function(ev, ui) {
|
||||
trigger('eventDragStart', eventElement, event, ev, ui);
|
||||
hideEvents(event, eventElement);
|
||||
origWidth = eventElement.width();
|
||||
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
dayDelta = colDelta * dis;
|
||||
if (!cell.row) {
|
||||
// on full-days
|
||||
renderDayOverlay(
|
||||
addDays(cloneDate(event.start), dayDelta),
|
||||
addDays(exclEndDay(event), dayDelta)
|
||||
);
|
||||
resetElement();
|
||||
}else{
|
||||
// mouse is over bottom slots
|
||||
if (isStart && allDay) {
|
||||
// convert event to temporary slot-event
|
||||
setOuterHeight(
|
||||
eventElement.width(colWidth - 10), // don't use entire width
|
||||
slotHeight * Math.round(
|
||||
(event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes'))
|
||||
/ opt('slotMinutes')
|
||||
)
|
||||
);
|
||||
eventElement.draggable('option', 'grid', [colWidth, 1]);
|
||||
allDay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ev, 'drag');
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
var cell = hoverListener.stop();
|
||||
clearOverlays();
|
||||
trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
if (cell && (!allDay || dayDelta)) {
|
||||
// changed!
|
||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||
var minuteDelta = 0;
|
||||
if (!allDay) {
|
||||
minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / slotHeight)
|
||||
* opt('slotMinutes')
|
||||
+ minMinute
|
||||
- (event.start.getHours() * 60 + event.start.getMinutes());
|
||||
}
|
||||
eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);
|
||||
}else{
|
||||
// hasn't moved or is out of bounds (draggable has already reverted)
|
||||
resetElement();
|
||||
if ($.browser.msie) {
|
||||
eventElement.css('filter', ''); // clear IE opacity side-effects
|
||||
}
|
||||
showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
function resetElement() {
|
||||
if (!allDay) {
|
||||
eventElement
|
||||
.width(origWidth)
|
||||
.height('')
|
||||
.draggable('option', 'grid', null);
|
||||
allDay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// when event starts out IN TIMESLOTS
|
||||
|
||||
function draggableSlotEvent(event, eventElement, timeElement) {
|
||||
if (!opt('disableDragging') && eventElement.draggable) {
|
||||
var origPosition;
|
||||
var allDay=false;
|
||||
var dayDelta;
|
||||
var minuteDelta;
|
||||
var prevMinuteDelta;
|
||||
var dis = opt('isRTL') ? -1 : 1;
|
||||
var hoverListener = getHoverListener();
|
||||
var colCnt = getColCnt();
|
||||
var colWidth = getColWidth();
|
||||
var slotHeight = getSlotHeight();
|
||||
eventElement.draggable({
|
||||
zIndex: 9,
|
||||
scroll: false,
|
||||
grid: [colWidth, slotHeight],
|
||||
axis: colCnt==1 ? 'y' : false,
|
||||
opacity: opt('dragOpacity'),
|
||||
revertDuration: opt('dragRevertDuration'),
|
||||
start: function(ev, ui) {
|
||||
trigger('eventDragStart', eventElement, event, ev, ui);
|
||||
hideEvents(event, eventElement);
|
||||
if ($.browser.msie) {
|
||||
eventElement.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
||||
}
|
||||
origPosition = eventElement.position();
|
||||
minuteDelta = prevMinuteDelta = 0;
|
||||
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||
eventElement.draggable('option', 'revert', !cell);
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
dayDelta = colDelta * dis;
|
||||
if (opt('allDaySlot') && !cell.row) {
|
||||
// over full days
|
||||
if (!allDay) {
|
||||
// convert to temporary all-day event
|
||||
allDay = true;
|
||||
timeElement.hide();
|
||||
eventElement.draggable('option', 'grid', null);
|
||||
}
|
||||
renderDayOverlay(
|
||||
addDays(cloneDate(event.start), dayDelta),
|
||||
addDays(exclEndDay(event), dayDelta)
|
||||
);
|
||||
}else{
|
||||
// on slots
|
||||
resetElement();
|
||||
}
|
||||
}
|
||||
}, ev, 'drag');
|
||||
},
|
||||
drag: function(ev, ui) {
|
||||
minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * opt('slotMinutes');
|
||||
if (minuteDelta != prevMinuteDelta) {
|
||||
if (!allDay) {
|
||||
updateTimeText(minuteDelta);
|
||||
}
|
||||
prevMinuteDelta = minuteDelta;
|
||||
}
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
var cell = hoverListener.stop();
|
||||
clearOverlays();
|
||||
trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
if (cell && (dayDelta || minuteDelta || allDay)) {
|
||||
// changed!
|
||||
eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);
|
||||
}else{
|
||||
// either no change or out-of-bounds (draggable has already reverted)
|
||||
resetElement();
|
||||
eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
|
||||
updateTimeText(0);
|
||||
if ($.browser.msie) {
|
||||
eventElement
|
||||
.css('filter', '') // clear IE opacity side-effects
|
||||
.find('span.fc-event-bg')
|
||||
.css('display', ''); // .show() made display=inline
|
||||
}
|
||||
showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
function updateTimeText(minuteDelta) {
|
||||
var newStart = addMinutes(cloneDate(event.start), minuteDelta);
|
||||
var newEnd;
|
||||
if (event.end) {
|
||||
newEnd = addMinutes(cloneDate(event.end), minuteDelta);
|
||||
}
|
||||
timeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));
|
||||
}
|
||||
function resetElement() {
|
||||
// convert back to original slot-event
|
||||
if (allDay) {
|
||||
timeElement.css('display', ''); // show() was causing display=inline
|
||||
eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
|
||||
allDay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Resizing
|
||||
--------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function resizableSlotEvent(event, eventElement, timeElement) {
|
||||
if (!opt('disableResizing') && eventElement.resizable) {
|
||||
var slotDelta, prevSlotDelta;
|
||||
var slotHeight = getSlotHeight();
|
||||
eventElement.resizable({
|
||||
handles: {
|
||||
s: 'div.ui-resizable-s'
|
||||
},
|
||||
grid: slotHeight,
|
||||
start: function(ev, ui) {
|
||||
slotDelta = prevSlotDelta = 0;
|
||||
hideEvents(event, eventElement);
|
||||
if ($.browser.msie && $.browser.version == '6.0') {
|
||||
eventElement.css('overflow', 'hidden');
|
||||
}
|
||||
eventElement.css('z-index', 9);
|
||||
trigger('eventResizeStart', this, event, ev, ui);
|
||||
},
|
||||
resize: function(ev, ui) {
|
||||
// don't rely on ui.size.height, doesn't take grid into account
|
||||
slotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight);
|
||||
if (slotDelta != prevSlotDelta) {
|
||||
timeElement.text(
|
||||
formatDates(
|
||||
event.start,
|
||||
(!slotDelta && !event.end) ? null : // no change, so don't display time range
|
||||
addMinutes(eventEnd(event), opt('slotMinutes')*slotDelta),
|
||||
opt('timeFormat')
|
||||
)
|
||||
);
|
||||
prevSlotDelta = slotDelta;
|
||||
}
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
trigger('eventResizeStop', this, event, ev, ui);
|
||||
if (slotDelta) {
|
||||
eventResize(this, event, 0, opt('slotMinutes')*slotDelta, ev, ui);
|
||||
}else{
|
||||
eventElement.css('z-index', 8);
|
||||
showEvents(event, eventElement);
|
||||
// BUG: if event was really short, need to put title back in span
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function countForwardSegs(levels) {
|
||||
var i, j, k, level, segForward, segBack;
|
||||
for (i=levels.length-1; i>0; i--) {
|
||||
level = levels[i];
|
||||
for (j=0; j<level.length; j++) {
|
||||
segForward = level[j];
|
||||
for (k=0; k<levels[i-1].length; k++) {
|
||||
segBack = levels[i-1][k];
|
||||
if (segsCollide(segForward, segBack)) {
|
||||
segBack.forward = Math.max(segBack.forward||0, (segForward.forward||0)+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
702
src/agenda/AgendaView.js
Normal file
|
@ -0,0 +1,702 @@
|
|||
|
||||
setDefaults({
|
||||
allDaySlot: true,
|
||||
allDayText: 'all-day',
|
||||
firstHour: 6,
|
||||
slotMinutes: 30,
|
||||
defaultEventMinutes: 120,
|
||||
axisFormat: 'h(:mm)tt',
|
||||
timeFormat: {
|
||||
agenda: 'h:mm{ - h:mm}'
|
||||
},
|
||||
dragOpacity: {
|
||||
agenda: .5
|
||||
},
|
||||
minTime: 0,
|
||||
maxTime: 24
|
||||
});
|
||||
|
||||
|
||||
function AgendaView(element, calendar, viewName) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderAgenda = renderAgenda;
|
||||
t.setWidth = setWidth;
|
||||
t.setHeight = setHeight;
|
||||
t.beforeHide = beforeHide;
|
||||
t.afterShow = afterShow;
|
||||
t.defaultEventEnd = defaultEventEnd;
|
||||
t.timePosition = timePosition;
|
||||
t.dayOfWeekCol = dayOfWeekCol;
|
||||
t.cellDate = cellDate;
|
||||
t.cellIsAllDay = cellIsAllDay;
|
||||
t.allDayTR = allDayTR;
|
||||
t.allDayBounds = allDayBounds;
|
||||
t.getHoverListener = function() { return hoverListener };
|
||||
t.colContentLeft = colContentLeft;
|
||||
t.colContentRight = colContentRight;
|
||||
t.getDaySegmentContainer = function() { return daySegmentContainer };
|
||||
t.getSlotSegmentContainer = function() { return slotSegmentContainer };
|
||||
t.getMinMinute = function() { return minMinute };
|
||||
t.getMaxMinute = function() { return maxMinute };
|
||||
t.getBodyContent = function() { return bodyContent };
|
||||
t.getRowCnt = function() { return 1 };
|
||||
t.getColCnt = function() { return colCnt };
|
||||
t.getColWidth = function() { return colWidth };
|
||||
t.getSlotHeight = function() { return slotHeight };
|
||||
t.defaultSelectionEnd = defaultSelectionEnd;
|
||||
t.renderDayOverlay = renderDayOverlay;
|
||||
t.renderSelection = renderSelection;
|
||||
t.clearSelection = clearSelection;
|
||||
t.dragStart = dragStart;
|
||||
t.dragStop = dragStop;
|
||||
|
||||
|
||||
// imports
|
||||
View.call(t, element, calendar, viewName);
|
||||
OverlayManager.call(t);
|
||||
SelectionManager.call(t);
|
||||
AgendaEventRenderer.call(t);
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var clearEvents = t.clearEvents;
|
||||
var renderOverlay = t.renderOverlay;
|
||||
var clearOverlays = t.clearOverlays;
|
||||
var reportSelection = t.reportSelection;
|
||||
var unselect = t.unselect;
|
||||
var daySelectionMousedown = t.daySelectionMousedown;
|
||||
var slotSegHtml = t.slotSegHtml;
|
||||
var formatDate = calendar.formatDate;
|
||||
|
||||
|
||||
// locals
|
||||
var head, body, bodyContent, bodyTable, bg;
|
||||
var colCnt;
|
||||
var slotCnt=0; // spanning all the way across
|
||||
var axisWidth, colWidth, slotHeight;
|
||||
var viewWidth, viewHeight;
|
||||
var savedScrollTop;
|
||||
var tm, firstDay;
|
||||
var nwe; // no weekends (int)
|
||||
var rtl, dis, dit; // day index sign / translate
|
||||
var minMinute, maxMinute;
|
||||
var coordinateGrid;
|
||||
var hoverListener;
|
||||
var colContentPositions;
|
||||
var slotTopCache = {};
|
||||
var selectionHelper;
|
||||
var daySegmentContainer;
|
||||
var slotSegmentContainer;
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
disableTextSelection(element.addClass('fc-agenda'));
|
||||
|
||||
|
||||
function renderAgenda(c) {
|
||||
|
||||
colCnt = c;
|
||||
|
||||
// update option-derived variables
|
||||
tm = opt('theme') ? 'ui' : 'fc';
|
||||
nwe = opt('weekends') ? 0 : 1;
|
||||
firstDay = opt('firstDay');
|
||||
if (rtl = opt('isRTL')) {
|
||||
dis = -1;
|
||||
dit = colCnt - 1;
|
||||
}else{
|
||||
dis = 1;
|
||||
dit = 0;
|
||||
}
|
||||
minMinute = parseTime(opt('minTime'));
|
||||
maxMinute = parseTime(opt('maxTime'));
|
||||
|
||||
var d0 = rtl ? addDays(cloneDate(t.visEnd), -1) : cloneDate(t.visStart),
|
||||
d = cloneDate(d0),
|
||||
today = clearTime(new Date()),
|
||||
colFormat = opt('columnFormat');
|
||||
|
||||
if (!head) { // first time rendering, build from scratch
|
||||
|
||||
var i,
|
||||
minutes,
|
||||
slotNormal = opt('slotMinutes') % 15 == 0, //...
|
||||
|
||||
// head
|
||||
s = "<div class='fc-agenda-head' style='position:relative;z-index:4'>" +
|
||||
"<table style='width:100%'>" +
|
||||
"<tr class='fc-first" + (opt('allDaySlot') ? '' : ' fc-last') + "'>" +
|
||||
"<th class='fc-leftmost " +
|
||||
tm + "-state-default'> </th>";
|
||||
for (i=0; i<colCnt; i++) {
|
||||
s += "<th class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default' +
|
||||
"'>" + formatDate(d, colFormat) + "</th>";
|
||||
addDays(d, dis);
|
||||
if (nwe) {
|
||||
skipWeekend(d, dis);
|
||||
}
|
||||
}
|
||||
s += "<th class='" + tm + "-state-default'> </th></tr>";
|
||||
if (opt('allDaySlot')) {
|
||||
s += "<tr class='fc-all-day'>" +
|
||||
"<th class='fc-axis fc-leftmost " + tm + "-state-default'>" + opt('allDayText') + "</th>" +
|
||||
"<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
|
||||
"<div class='fc-day-content'><div style='position:relative'> </div></div></td>" +
|
||||
"<th class='" + tm + "-state-default'> </th>" +
|
||||
"</tr><tr class='fc-divider fc-last'><th colspan='" + (colCnt+2) + "' class='" +
|
||||
tm + "-state-default fc-leftmost'><div/></th></tr>";
|
||||
}
|
||||
s+= "</table></div>";
|
||||
head = $(s).appendTo(element);
|
||||
dayBind(head.find('td'));
|
||||
|
||||
// all-day event container
|
||||
daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(head);
|
||||
|
||||
// body
|
||||
d = zeroDate();
|
||||
var maxd = addMinutes(cloneDate(d), maxMinute);
|
||||
addMinutes(d, minMinute);
|
||||
s = "<table>";
|
||||
for (i=0; d < maxd; i++) {
|
||||
minutes = d.getMinutes();
|
||||
s += "<tr class='" +
|
||||
(!i ? 'fc-first' : (!minutes ? '' : 'fc-minor')) +
|
||||
"'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
|
||||
((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +
|
||||
"</th><td class='fc-slot" + i + ' ' +
|
||||
tm + "-state-default'><div style='position:relative'> </div></td></tr>";
|
||||
addMinutes(d, opt('slotMinutes'));
|
||||
slotCnt++;
|
||||
}
|
||||
s += "</table>";
|
||||
body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>")
|
||||
.append(bodyContent = $("<div style='position:relative;overflow:hidden'>")
|
||||
.append(bodyTable = $(s)))
|
||||
.appendTo(element);
|
||||
slotBind(body.find('td'));
|
||||
|
||||
// slot event container
|
||||
slotSegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(bodyContent);
|
||||
|
||||
// background stripes
|
||||
d = cloneDate(d0);
|
||||
s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
|
||||
"<table style='width:100%;height:100%'><tr class='fc-first'>";
|
||||
for (i=0; i<colCnt; i++) {
|
||||
s += "<td class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default ' +
|
||||
(!i ? 'fc-leftmost ' : '') +
|
||||
(+d == +today ? tm + '-state-highlight fc-today' : 'fc-not-today') +
|
||||
"'><div class='fc-day-content'><div> </div></div></td>";
|
||||
addDays(d, dis);
|
||||
if (nwe) {
|
||||
skipWeekend(d, dis);
|
||||
}
|
||||
}
|
||||
s += "</tr></table></div>";
|
||||
bg = $(s).appendTo(element);
|
||||
|
||||
}else{ // skeleton already built, just modify it
|
||||
|
||||
clearEvents();
|
||||
|
||||
// redo column header text and class
|
||||
head.find('tr:first th').slice(1, -1).each(function(i, th) {
|
||||
$(th).text(formatDate(d, colFormat));
|
||||
th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
addDays(d, dis);
|
||||
if (nwe) {
|
||||
skipWeekend(d, dis);
|
||||
}
|
||||
});
|
||||
|
||||
// change classes of background stripes
|
||||
d = cloneDate(d0);
|
||||
bg.find('td').each(function(i, td) {
|
||||
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
if (+d == +today) {
|
||||
$(td)
|
||||
.removeClass('fc-not-today')
|
||||
.addClass('fc-today')
|
||||
.addClass(tm + '-state-highlight');
|
||||
}else{
|
||||
$(td)
|
||||
.addClass('fc-not-today')
|
||||
.removeClass('fc-today')
|
||||
.removeClass(tm + '-state-highlight');
|
||||
}
|
||||
addDays(d, dis);
|
||||
if (nwe) {
|
||||
skipWeekend(d, dis);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setHeight(height, dateChanged) {
|
||||
|
||||
if (height === undefined) {
|
||||
height = viewHeight;
|
||||
}
|
||||
|
||||
viewHeight = height;
|
||||
slotTopCache = {};
|
||||
|
||||
body.height(height - head.height());
|
||||
|
||||
slotHeight = body.find('tr:first div').height() + 1;
|
||||
|
||||
bg.css({
|
||||
top: head.find('tr').height(),
|
||||
height: height
|
||||
});
|
||||
|
||||
if (dateChanged) {
|
||||
resetScroll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setWidth(width) {
|
||||
viewWidth = width;
|
||||
colContentPositions.clear();
|
||||
|
||||
body.width(width);
|
||||
bodyTable.width('');
|
||||
|
||||
var topTDs = head.find('tr:first th'),
|
||||
stripeTDs = bg.find('td'),
|
||||
clientWidth = body[0].clientWidth;
|
||||
|
||||
bodyTable.width(clientWidth);
|
||||
|
||||
// time-axis width
|
||||
axisWidth = 0;
|
||||
setOuterWidth(
|
||||
head.find('tr:lt(2) th:first').add(body.find('tr:first th'))
|
||||
.width('')
|
||||
.each(function() {
|
||||
axisWidth = Math.max(axisWidth, $(this).outerWidth());
|
||||
}),
|
||||
axisWidth
|
||||
);
|
||||
axisWidth = axisWidth;
|
||||
|
||||
// column width
|
||||
colWidth = Math.floor((clientWidth - axisWidth) / colCnt);
|
||||
setOuterWidth(stripeTDs.slice(0, -1), colWidth);
|
||||
setOuterWidth(topTDs.slice(1, -2), colWidth);
|
||||
setOuterWidth(topTDs.slice(-2, -1), clientWidth - axisWidth - colWidth*(colCnt-1));
|
||||
|
||||
bg.css({
|
||||
left: axisWidth,
|
||||
width: clientWidth - axisWidth
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function resetScroll() {
|
||||
var d0 = zeroDate(),
|
||||
scrollDate = cloneDate(d0);
|
||||
scrollDate.setHours(opt('firstHour'));
|
||||
var top = timePosition(d0, scrollDate) + 1, // +1 for the border
|
||||
scroll = function() {
|
||||
body.scrollTop(top);
|
||||
};
|
||||
scroll();
|
||||
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
|
||||
}
|
||||
|
||||
|
||||
function beforeHide() {
|
||||
savedScrollTop = body.scrollTop();
|
||||
}
|
||||
|
||||
|
||||
function afterShow() {
|
||||
body.scrollTop(savedScrollTop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Slot/Day clicking and binding
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function dayBind(tds) {
|
||||
tds.click(slotClick)
|
||||
.mousedown(daySelectionMousedown);
|
||||
}
|
||||
|
||||
|
||||
function slotBind(tds) {
|
||||
tds.click(slotClick)
|
||||
.mousedown(slotSelectionMousedown);
|
||||
}
|
||||
|
||||
|
||||
function slotClick(ev) {
|
||||
if (!opt('selectable')) { // SelectionManager will worry about dayClick
|
||||
var col = Math.min(colCnt-1, Math.floor((ev.pageX - bg.offset().left) / colWidth)),
|
||||
date = addDays(cloneDate(t.visStart), col*dis+dit),
|
||||
rowMatch = this.className.match(/fc-slot(\d+)/);
|
||||
if (rowMatch) {
|
||||
var mins = parseInt(rowMatch[1]) * opt('slotMinutes'),
|
||||
hours = Math.floor(mins/60);
|
||||
date.setHours(hours);
|
||||
date.setMinutes(mins%60 + minMinute);
|
||||
trigger('dayClick', this, date, false, ev);
|
||||
}else{
|
||||
trigger('dayClick', this, date, true, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Semi-transparent Overlay Helpers
|
||||
-----------------------------------------------------*/
|
||||
|
||||
|
||||
function renderDayOverlay(startDate, endDate, refreshCoordinateGrid) { // endDate is exclusive
|
||||
if (refreshCoordinateGrid) {
|
||||
coordinateGrid.build();
|
||||
}
|
||||
var visStart = cloneDate(t.visStart);
|
||||
var startCol, endCol;
|
||||
if (rtl) {
|
||||
startCol = dayDiff(endDate, visStart)*dis+dit+1;
|
||||
endCol = dayDiff(startDate, visStart)*dis+dit+1;
|
||||
}else{
|
||||
startCol = dayDiff(startDate, visStart);
|
||||
endCol = dayDiff(endDate, visStart);
|
||||
}
|
||||
startCol = Math.max(0, startCol);
|
||||
endCol = Math.min(colCnt, endCol);
|
||||
if (startCol < endCol) {
|
||||
dayBind(
|
||||
renderCellOverlay(0, startCol, 0, endCol-1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function renderCellOverlay(col0, row0, col1, row1) {
|
||||
var rect = coordinateGrid.rect(col0, row0, col1, row1, head);
|
||||
return renderOverlay(rect, head);
|
||||
}
|
||||
|
||||
|
||||
function renderSlotOverlay(overlayStart, overlayEnd) {
|
||||
var dayStart = cloneDate(t.visStart);
|
||||
var dayEnd = addDays(cloneDate(dayStart), 1);
|
||||
for (var i=0; i<colCnt; i++) {
|
||||
var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
||||
var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
||||
if (stretchStart < stretchEnd) {
|
||||
var col = i*dis+dit;
|
||||
var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only use it for horizontal coords
|
||||
var top = timePosition(dayStart, stretchStart);
|
||||
var bottom = timePosition(dayStart, stretchEnd);
|
||||
rect.top = top;
|
||||
rect.height = bottom - top;
|
||||
slotBind(
|
||||
renderOverlay(rect, bodyContent)
|
||||
);
|
||||
}
|
||||
addDays(dayStart, 1);
|
||||
addDays(dayEnd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Coordinate Utilities
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
||||
var e, n, p;
|
||||
bg.find('td').each(function(i, _e) {
|
||||
e = $(_e);
|
||||
n = e.offset().left;
|
||||
if (i) {
|
||||
p[1] = n;
|
||||
}
|
||||
p = [n];
|
||||
cols[i] = p;
|
||||
});
|
||||
p[1] = n + e.outerWidth();
|
||||
if (opt('allDaySlot')) {
|
||||
e = head.find('td');
|
||||
n = e.offset().top;
|
||||
rows[0] = [n, n+e.outerHeight()];
|
||||
}
|
||||
var bodyContentTop = bodyContent.offset().top;
|
||||
var bodyTop = body.offset().top;
|
||||
var bodyBottom = bodyTop + body.outerHeight();
|
||||
function constrain(n) {
|
||||
return Math.max(bodyTop, Math.min(bodyBottom, n));
|
||||
}
|
||||
for (var i=0; i<slotCnt; i++) {
|
||||
rows.push([
|
||||
constrain(bodyContentTop + slotHeight*i),
|
||||
constrain(bodyContentTop + slotHeight*(i+1))
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
hoverListener = new HoverListener(coordinateGrid);
|
||||
|
||||
|
||||
colContentPositions = new HorizontalPositionCache(function(col) {
|
||||
return bg.find('td:eq(' + col + ') div div');
|
||||
});
|
||||
|
||||
|
||||
function colContentLeft(col) {
|
||||
return axisWidth + colContentPositions.left(col);
|
||||
}
|
||||
|
||||
|
||||
function colContentRight(col) {
|
||||
return axisWidth + colContentPositions.right(col);
|
||||
}
|
||||
|
||||
|
||||
function dayOfWeekCol(dayOfWeek) {
|
||||
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||
}
|
||||
|
||||
|
||||
// get the Y coordinate of the given time on the given day (both Date objects)
|
||||
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
||||
day = cloneDate(day, true);
|
||||
if (time < addMinutes(cloneDate(day), minMinute)) {
|
||||
return 0;
|
||||
}
|
||||
if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
||||
return bodyContent.height();
|
||||
}
|
||||
var slotMinutes = opt('slotMinutes'),
|
||||
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
||||
slotI = Math.floor(minutes / slotMinutes),
|
||||
slotTop = slotTopCache[slotI];
|
||||
if (slotTop === undefined) {
|
||||
slotTop = slotTopCache[slotI] = body.find('tr:eq(' + slotI + ') td div')[0].offsetTop;
|
||||
}
|
||||
return Math.max(0, Math.round(
|
||||
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
function cellDate(cell) {
|
||||
var d = addDays(cloneDate(t.visStart), cell.col*dis+dit);
|
||||
var slotIndex = cell.row;
|
||||
if (opt('allDaySlot')) {
|
||||
slotIndex--;
|
||||
}
|
||||
if (slotIndex >= 0) {
|
||||
addMinutes(d, minMinute + slotIndex*opt('slotMinutes'));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
function cellIsAllDay(cell) {
|
||||
return opt('allDaySlot') && !cell.row;
|
||||
}
|
||||
|
||||
|
||||
function allDayBounds() {
|
||||
return {
|
||||
left: axisWidth,
|
||||
right: viewWidth
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function allDayTR(index) {
|
||||
return head.find('tr.fc-all-day');
|
||||
}
|
||||
|
||||
|
||||
function defaultEventEnd(event) {
|
||||
var start = cloneDate(event.start);
|
||||
if (event.allDay) {
|
||||
return start;
|
||||
}
|
||||
return addMinutes(start, opt('defaultEventMinutes'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Selection
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function defaultSelectionEnd(startDate, allDay) {
|
||||
if (allDay) {
|
||||
return cloneDate(startDate);
|
||||
}
|
||||
return addMinutes(cloneDate(startDate), opt('slotMinutes'));
|
||||
}
|
||||
|
||||
|
||||
function renderSelection(startDate, endDate, allDay) {
|
||||
if (allDay) {
|
||||
if (opt('allDaySlot')) {
|
||||
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
|
||||
}
|
||||
}else{
|
||||
renderSlotSelection(startDate, endDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function renderSlotSelection(startDate, endDate) {
|
||||
var helperOption = opt('selectHelper');
|
||||
coordinateGrid.build();
|
||||
if (helperOption) {
|
||||
var col = dayDiff(startDate, t.visStart) * dis + dit;
|
||||
if (col >= 0 && col < colCnt) { // only works when times are on same day
|
||||
var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only for horizontal coords
|
||||
var top = timePosition(startDate, startDate);
|
||||
var bottom = timePosition(startDate, endDate);
|
||||
if (bottom > top) { // protect against selections that are entirely before or after visible range
|
||||
rect.top = top;
|
||||
rect.height = bottom - top;
|
||||
rect.left += 2;
|
||||
rect.width -= 5;
|
||||
if ($.isFunction(helperOption)) {
|
||||
var helperRes = helperOption(startDate, endDate);
|
||||
if (helperRes) {
|
||||
rect.position = 'absolute';
|
||||
rect.zIndex = 8;
|
||||
selectionHelper = $(helperRes)
|
||||
.css(rect)
|
||||
.appendTo(bodyContent);
|
||||
}
|
||||
}else{
|
||||
selectionHelper = $(slotSegHtml(
|
||||
{
|
||||
title: '',
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
className: [],
|
||||
editable: false
|
||||
},
|
||||
rect,
|
||||
'fc-event fc-event-vert fc-corner-top fc-corner-bottom '
|
||||
));
|
||||
if ($.browser.msie) {
|
||||
selectionHelper.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
||||
}
|
||||
selectionHelper.css('opacity', opt('dragOpacity'));
|
||||
}
|
||||
if (selectionHelper) {
|
||||
slotBind(selectionHelper);
|
||||
bodyContent.append(selectionHelper);
|
||||
setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended
|
||||
setOuterHeight(selectionHelper, rect.height, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
renderSlotOverlay(startDate, endDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function clearSelection() {
|
||||
clearOverlays();
|
||||
if (selectionHelper) {
|
||||
selectionHelper.remove();
|
||||
selectionHelper = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function slotSelectionMousedown(ev) {
|
||||
if (opt('selectable')) {
|
||||
unselect(ev);
|
||||
var _mousedownElement = this;
|
||||
var dates;
|
||||
hoverListener.start(function(cell, origCell) {
|
||||
clearSelection();
|
||||
if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {
|
||||
var d1 = cellDate(origCell);
|
||||
var d2 = cellDate(cell);
|
||||
dates = [
|
||||
d1,
|
||||
addMinutes(cloneDate(d1), opt('slotMinutes')),
|
||||
d2,
|
||||
addMinutes(cloneDate(d2), opt('slotMinutes'))
|
||||
].sort(cmp);
|
||||
renderSlotSelection(dates[0], dates[3]);
|
||||
}else{
|
||||
dates = null;
|
||||
}
|
||||
}, ev);
|
||||
$(document).one('mouseup', function(ev) {
|
||||
hoverListener.stop();
|
||||
if (dates) {
|
||||
if (+dates[0] == +dates[1]) {
|
||||
trigger('dayClick', _mousedownElement, dates[0], false, ev);
|
||||
// BUG: _mousedownElement will sometimes be the overlay
|
||||
}
|
||||
reportSelection(dates[0], dates[3], false, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* External Dragging
|
||||
--------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function dragStart(_dragElement, ev, ui) {
|
||||
hoverListener.start(function(cell) {
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
if (cellIsAllDay(cell)) {
|
||||
renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
|
||||
}else{
|
||||
var d1 = cellDate(cell);
|
||||
var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));
|
||||
renderSlotOverlay(d1, d2);
|
||||
}
|
||||
}
|
||||
}, ev);
|
||||
}
|
||||
|
||||
|
||||
function dragStop(_dragElement, ev, ui) {
|
||||
var cell = hoverListener.stop();
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
46
src/agenda/AgendaWeekView.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
fcViews.agendaWeek = AgendaWeekView;
|
||||
|
||||
function AgendaWeekView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
|
||||
|
||||
// imports
|
||||
AgendaView.call(t, element, calendar, 'agendaWeek');
|
||||
var opt = t.opt;
|
||||
var renderAgenda = t.renderAgenda;
|
||||
var formatDates = calendar.formatDates;
|
||||
|
||||
|
||||
|
||||
function render(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta * 7);
|
||||
}
|
||||
var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
|
||||
var end = addDays(cloneDate(start), 7);
|
||||
var visStart = cloneDate(start);
|
||||
var visEnd = cloneDate(end);
|
||||
var weekends = opt('weekends');
|
||||
if (!weekends) {
|
||||
skipWeekend(visStart);
|
||||
skipWeekend(visEnd, -1, true);
|
||||
}
|
||||
t.title = formatDates(
|
||||
visStart,
|
||||
addDays(cloneDate(visEnd), -1),
|
||||
opt('titleFormat')
|
||||
);
|
||||
t.start = start;
|
||||
t.end = end;
|
||||
t.visStart = visStart;
|
||||
t.visEnd = visEnd;
|
||||
renderAgenda(weekends ? 7 : 5);
|
||||
}
|
||||
|
||||
|
||||
}
|
37
src/basic/BasicDayView.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
fcViews.basicDay = BasicDayView;
|
||||
|
||||
//TODO: when calendar's date starts out on a weekend, shouldn't happen
|
||||
|
||||
|
||||
function BasicDayView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
|
||||
|
||||
// imports
|
||||
BasicView.call(t, element, calendar, 'basicDay');
|
||||
var opt = t.opt;
|
||||
var renderBasic = t.renderBasic;
|
||||
var formatDate = calendar.formatDate;
|
||||
|
||||
|
||||
|
||||
function render(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta);
|
||||
if (!opt('weekends')) {
|
||||
skipWeekend(date, delta < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
t.title = formatDate(date, opt('titleFormat'));
|
||||
t.start = t.visStart = cloneDate(date, true);
|
||||
t.end = t.visEnd = addDays(cloneDate(t.start), 1);
|
||||
renderBasic(1, 1, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
149
src/basic/BasicEventRenderer.js
Normal file
|
@ -0,0 +1,149 @@
|
|||
|
||||
function BasicEventRenderer() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderEvents = renderEvents;
|
||||
t.rerenderEvents = rerenderEvents;
|
||||
t.clearEvents = clearEvents;
|
||||
t.bindDaySeg = bindDaySeg;
|
||||
|
||||
|
||||
// imports
|
||||
DayEventRenderer.call(t);
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var reportEvents = t.reportEvents;
|
||||
var clearEventData = t.clearEventData;
|
||||
var eventElementHandlers = t.eventElementHandlers;
|
||||
var showEvents = t.showEvents;
|
||||
var hideEvents = t.hideEvents;
|
||||
var eventDrop = t.eventDrop;
|
||||
var getDaySegmentContainer = t.getDaySegmentContainer;
|
||||
var getHoverListener = t.getHoverListener;
|
||||
var renderDayOverlay = t.renderDayOverlay;
|
||||
var clearOverlays = t.clearOverlays;
|
||||
var getRowCnt = t.getRowCnt;
|
||||
var getColCnt = t.getColCnt;
|
||||
var renderDaySegs = t.renderDaySegs;
|
||||
var resizableDayEvent = t.resizableDayEvent;
|
||||
|
||||
|
||||
// locals
|
||||
var cachedEvents=[];
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function renderEvents(events) {
|
||||
reportEvents(cachedEvents = events);
|
||||
renderDaySegs(compileSegs(events));
|
||||
}
|
||||
|
||||
|
||||
function rerenderEvents(modifiedEventId) {
|
||||
clearEvents();
|
||||
renderDaySegs(compileSegs(cachedEvents), modifiedEventId);
|
||||
}
|
||||
|
||||
|
||||
function clearEvents() {
|
||||
clearEventData();
|
||||
getDaySegmentContainer().empty();
|
||||
}
|
||||
|
||||
|
||||
function compileSegs(events) {
|
||||
var rowCnt = getRowCnt(),
|
||||
colCnt = getColCnt(),
|
||||
d1 = cloneDate(t.visStart),
|
||||
d2 = addDays(cloneDate(d1), colCnt),
|
||||
visEventsEnds = $.map(events, exclEndDay),
|
||||
i, row,
|
||||
j, level,
|
||||
k, seg,
|
||||
segs=[];
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
row = stackSegs(sliceSegs(events, visEventsEnds, d1, d2));
|
||||
for (j=0; j<row.length; j++) {
|
||||
level = row[j];
|
||||
for (k=0; k<level.length; k++) {
|
||||
seg = level[k];
|
||||
seg.row = i;
|
||||
seg.level = j;
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
addDays(d1, 7);
|
||||
addDays(d2, 7);
|
||||
}
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
||||
function bindDaySeg(event, eventElement, seg) {
|
||||
eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && opt('editable')) {
|
||||
draggableDayEvent(event, eventElement);
|
||||
if (seg.isEnd) {
|
||||
resizableDayEvent(event, eventElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Dragging
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function draggableDayEvent(event, eventElement) {
|
||||
if (!opt('disableDragging') && eventElement.draggable) {
|
||||
var hoverListener = getHoverListener();
|
||||
var dayDelta;
|
||||
eventElement.draggable({
|
||||
zIndex: 9,
|
||||
delay: 50,
|
||||
opacity: opt('dragOpacity'),
|
||||
revertDuration: opt('dragRevertDuration'),
|
||||
start: function(ev, ui) {
|
||||
trigger('eventDragStart', eventElement, event, ev, ui);
|
||||
hideEvents(event, eventElement);
|
||||
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
dayDelta = rowDelta*7 + colDelta * (opt('isRTL') ? -1 : 1);
|
||||
renderDayOverlay(
|
||||
addDays(cloneDate(event.start), dayDelta),
|
||||
addDays(exclEndDay(event), dayDelta)
|
||||
);
|
||||
}else{
|
||||
dayDelta = 0;
|
||||
}
|
||||
}, ev, 'drag');
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
hoverListener.stop();
|
||||
clearOverlays();
|
||||
trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
if (dayDelta) {
|
||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||
eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
|
||||
}else{
|
||||
if ($.browser.msie) {
|
||||
eventElement.css('filter', ''); // clear IE opacity side-effects
|
||||
}
|
||||
showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
453
src/basic/BasicView.js
Normal file
|
@ -0,0 +1,453 @@
|
|||
|
||||
var tdHeightBug;
|
||||
|
||||
setDefaults({
|
||||
weekMode: 'fixed'
|
||||
});
|
||||
|
||||
|
||||
function BasicView(element, calendar, viewName) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderBasic = renderBasic;
|
||||
t.setHeight = setHeight;
|
||||
t.setWidth = setWidth;
|
||||
t.renderDayOverlay = renderDayOverlay;
|
||||
t.defaultSelectionEnd = defaultSelectionEnd;
|
||||
t.renderSelection = renderSelection;
|
||||
t.clearSelection = clearSelection;
|
||||
t.dragStart = dragStart;
|
||||
t.dragStop = dragStop;
|
||||
t.defaultEventEnd = defaultEventEnd;
|
||||
t.getHoverListener = function() { return hoverListener };
|
||||
t.colContentLeft = colContentLeft;
|
||||
t.colContentRight = colContentRight;
|
||||
t.dayOfWeekCol = dayOfWeekCol;
|
||||
t.cellDate = cellDate;
|
||||
t.cellIsAllDay = function() { return true };
|
||||
t.allDayTR = allDayTR;
|
||||
t.allDayBounds = allDayBounds;
|
||||
t.getRowCnt = function() { return rowCnt };
|
||||
t.getColCnt = function() { return colCnt };
|
||||
t.getColWidth = function() { return colWidth };
|
||||
t.getDaySegmentContainer = function() { return daySegmentContainer };
|
||||
|
||||
|
||||
// imports
|
||||
View.call(t, element, calendar, viewName);
|
||||
OverlayManager.call(t);
|
||||
SelectionManager.call(t);
|
||||
BasicEventRenderer.call(t);
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var clearEvents = t.clearEvents;
|
||||
var renderOverlay = t.renderOverlay;
|
||||
var clearOverlays = t.clearOverlays;
|
||||
var daySelectionMousedown = t.daySelectionMousedown;
|
||||
var formatDate = calendar.formatDate;
|
||||
|
||||
|
||||
// locals
|
||||
var rtl, dis, dit;
|
||||
var firstDay;
|
||||
var nwe;
|
||||
var rowCnt, colCnt;
|
||||
var colWidth;
|
||||
var viewWidth, viewHeight;
|
||||
var thead, tbody;
|
||||
var daySegmentContainer;
|
||||
var coordinateGrid;
|
||||
var hoverListener;
|
||||
var colContentPositions;
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
------------------------------------------------------------*/
|
||||
|
||||
|
||||
disableTextSelection(element.addClass('fc-grid'));
|
||||
|
||||
|
||||
function renderBasic(r, c, showNumbers) {
|
||||
|
||||
rowCnt = r;
|
||||
colCnt = c;
|
||||
rtl = opt('isRTL');
|
||||
if (rtl) {
|
||||
dis = -1;
|
||||
dit = colCnt - 1;
|
||||
}else{
|
||||
dis = 1;
|
||||
dit = 0;
|
||||
}
|
||||
firstDay = opt('firstDay');
|
||||
nwe = opt('weekends') ? 0 : 1;
|
||||
|
||||
var tm = opt('theme') ? 'ui' : 'fc';
|
||||
var colFormat = opt('columnFormat');
|
||||
var month = t.start.getMonth();
|
||||
var today = clearTime(new Date());
|
||||
var s, i, j, d = cloneDate(t.visStart);
|
||||
|
||||
if (!tbody) { // first time, build all cells from scratch
|
||||
|
||||
var table = $("<table/>").appendTo(element);
|
||||
|
||||
s = "<thead><tr>";
|
||||
for (i=0; i<colCnt; i++) {
|
||||
s += "<th class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default' +
|
||||
(i==dit ? ' fc-leftmost' : '') +
|
||||
"'>" + formatDate(d, colFormat) + "</th>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
thead = $(s + "</tr></thead>").appendTo(table);
|
||||
|
||||
s = "<tbody>";
|
||||
d = cloneDate(t.visStart);
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
s += "<tr class='fc-week" + i + "'>";
|
||||
for (j=0; j<colCnt; j++) {
|
||||
s += "<td class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default fc-day' + (i*colCnt+j) +
|
||||
(j==dit ? ' fc-leftmost' : '') +
|
||||
(rowCnt>1 && d.getMonth() != month ? ' fc-other-month' : '') +
|
||||
(+d == +today ?
|
||||
' fc-today '+tm+'-state-highlight' :
|
||||
' fc-not-today') + "'>" +
|
||||
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
|
||||
"<div class='fc-day-content'><div style='position:relative'> </div></div></td>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
s += "</tr>";
|
||||
}
|
||||
tbody = $(s + "</tbody>").appendTo(table);
|
||||
dayBind(tbody.find('td'));
|
||||
|
||||
daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(element);
|
||||
|
||||
}else{ // NOT first time, reuse as many cells as possible
|
||||
|
||||
clearEvents();
|
||||
|
||||
var prevRowCnt = tbody.find('tr').length;
|
||||
if (rowCnt < prevRowCnt) {
|
||||
tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows
|
||||
}
|
||||
else if (rowCnt > prevRowCnt) { // needs to create new rows...
|
||||
s = '';
|
||||
for (i=prevRowCnt; i<rowCnt; i++) {
|
||||
s += "<tr class='fc-week" + i + "'>";
|
||||
for (j=0; j<colCnt; j++) {
|
||||
s += "<td class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
|
||||
(j==dit ? ' fc-leftmost' : '') + "'>" +
|
||||
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
|
||||
"<div class='fc-day-content'><div style='position:relative'> </div></div>" +
|
||||
"</td>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
s += "</tr>";
|
||||
}
|
||||
tbody.append(s);
|
||||
}
|
||||
dayBind(tbody.find('td.fc-new').removeClass('fc-new'));
|
||||
|
||||
// re-label and re-class existing cells
|
||||
d = cloneDate(t.visStart);
|
||||
tbody.find('td').each(function() {
|
||||
var td = $(this);
|
||||
if (rowCnt > 1) {
|
||||
if (d.getMonth() == month) {
|
||||
td.removeClass('fc-other-month');
|
||||
}else{
|
||||
td.addClass('fc-other-month');
|
||||
}
|
||||
}
|
||||
if (+d == +today) {
|
||||
td.removeClass('fc-not-today')
|
||||
.addClass('fc-today')
|
||||
.addClass(tm + '-state-highlight');
|
||||
}else{
|
||||
td.addClass('fc-not-today')
|
||||
.removeClass('fc-today')
|
||||
.removeClass(tm + '-state-highlight');
|
||||
}
|
||||
td.find('div.fc-day-number').text(d.getDate());
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
if (rowCnt == 1) { // more changes likely (week or day view)
|
||||
|
||||
// redo column header text and class
|
||||
d = cloneDate(t.visStart);
|
||||
thead.find('th').each(function(i, th) {
|
||||
$(th).text(formatDate(d, colFormat));
|
||||
th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
// redo cell day-of-weeks
|
||||
d = cloneDate(t.visStart);
|
||||
tbody.find('td').each(function(i, td) {
|
||||
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function setHeight(height) {
|
||||
viewHeight = height;
|
||||
var leftTDs = tbody.find('tr td:first-child'),
|
||||
tbodyHeight = viewHeight - thead.height(),
|
||||
rowHeight1, rowHeight2;
|
||||
if (opt('weekMode') == 'variable') {
|
||||
rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6));
|
||||
}else{
|
||||
rowHeight1 = Math.floor(tbodyHeight / rowCnt);
|
||||
rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
|
||||
}
|
||||
if (tdHeightBug === undefined) {
|
||||
// bug in firefox where cell height includes padding
|
||||
var tr = tbody.find('tr:first'),
|
||||
td = tr.find('td:first');
|
||||
td.height(rowHeight1);
|
||||
tdHeightBug = rowHeight1 != td.height();
|
||||
}
|
||||
if (tdHeightBug) {
|
||||
leftTDs.slice(0, -1).height(rowHeight1);
|
||||
leftTDs.slice(-1).height(rowHeight2);
|
||||
}else{
|
||||
setOuterHeight(leftTDs.slice(0, -1), rowHeight1);
|
||||
setOuterHeight(leftTDs.slice(-1), rowHeight2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setWidth(width) {
|
||||
viewWidth = width;
|
||||
colContentPositions.clear();
|
||||
colWidth = Math.floor(viewWidth / colCnt);
|
||||
setOuterWidth(thead.find('th').slice(0, -1), colWidth);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Day clicking and binding
|
||||
-----------------------------------------------------------*/
|
||||
|
||||
|
||||
function dayBind(days) {
|
||||
days.click(dayClick)
|
||||
.mousedown(daySelectionMousedown);
|
||||
}
|
||||
|
||||
|
||||
function dayClick(ev) {
|
||||
if (!opt('selectable')) { // SelectionManager will worry about dayClick
|
||||
var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]),
|
||||
date = addDays(
|
||||
cloneDate(t.visStart),
|
||||
Math.floor(n/colCnt) * 7 + n % colCnt
|
||||
);
|
||||
// TODO: what about weekends in middle of week?
|
||||
trigger('dayClick', this, date, true, ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Semi-transparent Overlay Helpers
|
||||
------------------------------------------------------*/
|
||||
|
||||
|
||||
function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive
|
||||
if (refreshCoordinateGrid) {
|
||||
coordinateGrid.build();
|
||||
}
|
||||
var rowStart = cloneDate(t.visStart);
|
||||
var rowEnd = addDays(cloneDate(rowStart), colCnt);
|
||||
for (var i=0; i<rowCnt; i++) {
|
||||
var stretchStart = new Date(Math.max(rowStart, overlayStart));
|
||||
var stretchEnd = new Date(Math.min(rowEnd, overlayEnd));
|
||||
if (stretchStart < stretchEnd) {
|
||||
var colStart, colEnd;
|
||||
if (rtl) {
|
||||
colStart = dayDiff(stretchEnd, rowStart)*dis+dit+1;
|
||||
colEnd = dayDiff(stretchStart, rowStart)*dis+dit+1;
|
||||
}else{
|
||||
colStart = dayDiff(stretchStart, rowStart);
|
||||
colEnd = dayDiff(stretchEnd, rowStart);
|
||||
}
|
||||
dayBind(
|
||||
renderCellOverlay(i, colStart, i, colEnd-1)
|
||||
);
|
||||
}
|
||||
addDays(rowStart, 7);
|
||||
addDays(rowEnd, 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function renderCellOverlay(row0, col0, row1, col1) { // row1,col1 is inclusive
|
||||
var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
|
||||
return renderOverlay(rect, element);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Selection
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function defaultSelectionEnd(startDate, allDay) {
|
||||
return cloneDate(startDate);
|
||||
}
|
||||
|
||||
|
||||
function renderSelection(startDate, endDate, allDay) {
|
||||
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
|
||||
}
|
||||
|
||||
|
||||
function clearSelection() {
|
||||
clearOverlays();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* External Dragging
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function dragStart(_dragElement, ev, ui) {
|
||||
hoverListener.start(function(cell) {
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
|
||||
}
|
||||
}, ev);
|
||||
}
|
||||
|
||||
|
||||
function dragStop(_dragElement, ev, ui) {
|
||||
var cell = hoverListener.stop();
|
||||
clearOverlays();
|
||||
if (cell) {
|
||||
var d = cellDate(cell);
|
||||
trigger('drop', _dragElement, d, true, ev, ui);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Utilities
|
||||
--------------------------------------------------------*/
|
||||
|
||||
|
||||
function defaultEventEnd(event) {
|
||||
return cloneDate(event.start);
|
||||
}
|
||||
|
||||
|
||||
coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
||||
var e, n, p;
|
||||
var tds = tbody.find('tr:first td');
|
||||
if (rtl) {
|
||||
tds = $(tds.get().reverse());
|
||||
}
|
||||
tds.each(function(i, _e) {
|
||||
e = $(_e);
|
||||
n = e.offset().left;
|
||||
if (i) {
|
||||
p[1] = n;
|
||||
}
|
||||
p = [n];
|
||||
cols[i] = p;
|
||||
});
|
||||
p[1] = n + e.outerWidth();
|
||||
tbody.find('tr').each(function(i, _e) {
|
||||
e = $(_e);
|
||||
n = e.offset().top;
|
||||
if (i) {
|
||||
p[1] = n;
|
||||
}
|
||||
p = [n];
|
||||
rows[i] = p;
|
||||
});
|
||||
p[1] = n + e.outerHeight();
|
||||
});
|
||||
|
||||
|
||||
hoverListener = new HoverListener(coordinateGrid);
|
||||
|
||||
|
||||
colContentPositions = new HorizontalPositionCache(function(col) {
|
||||
return tbody.find('td:eq(' + col + ') div div');
|
||||
});
|
||||
|
||||
|
||||
function colContentLeft(col) {
|
||||
return colContentPositions.left(col);
|
||||
}
|
||||
|
||||
|
||||
function colContentRight(col) {
|
||||
return colContentPositions.right(col);
|
||||
}
|
||||
|
||||
|
||||
function dayOfWeekCol(dayOfWeek) {
|
||||
return (dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt;
|
||||
}
|
||||
|
||||
|
||||
function cellDate(cell) {
|
||||
return addDays(cloneDate(t.visStart), cell.row*7 + cell.col*dis+dit);
|
||||
// TODO: what about weekends in middle of week?
|
||||
}
|
||||
|
||||
|
||||
function allDayTR(i) {
|
||||
return tbody.find('tr:eq('+i+')');
|
||||
}
|
||||
|
||||
|
||||
function allDayBounds(i) {
|
||||
return {
|
||||
left: 0,
|
||||
right: viewWidth
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
46
src/basic/BasicWeekView.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
fcViews.basicWeek = BasicWeekView;
|
||||
|
||||
function BasicWeekView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
|
||||
|
||||
// imports
|
||||
BasicView.call(t, element, calendar, 'basicWeek');
|
||||
var opt = t.opt;
|
||||
var renderBasic = t.renderBasic;
|
||||
var formatDates = calendar.formatDates;
|
||||
|
||||
|
||||
|
||||
function render(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta * 7);
|
||||
}
|
||||
var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
|
||||
var end = addDays(cloneDate(start), 7);
|
||||
var visStart = cloneDate(start);
|
||||
var visEnd = cloneDate(end);
|
||||
var weekends = opt('weekends');
|
||||
if (!weekends) {
|
||||
skipWeekend(visStart);
|
||||
skipWeekend(visEnd, -1, true);
|
||||
}
|
||||
t.title = formatDates(
|
||||
visStart,
|
||||
addDays(cloneDate(visEnd), -1),
|
||||
opt('titleFormat')
|
||||
);
|
||||
t.start = start;
|
||||
t.end = end;
|
||||
t.visStart = visStart;
|
||||
t.visEnd = visEnd;
|
||||
renderBasic(1, weekends ? 7 : 5, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
52
src/basic/MonthView.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
fcViews.month = MonthView;
|
||||
|
||||
function MonthView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
|
||||
|
||||
// imports
|
||||
BasicView.call(t, element, calendar, 'month');
|
||||
var opt = t.opt;
|
||||
var renderBasic = t.renderBasic;
|
||||
var formatDate = calendar.formatDate;
|
||||
|
||||
|
||||
|
||||
function render(date, delta) {
|
||||
if (delta) {
|
||||
addMonths(date, delta);
|
||||
date.setDate(1);
|
||||
}
|
||||
var start = cloneDate(date, true);
|
||||
start.setDate(1);
|
||||
var end = addMonths(cloneDate(start), 1);
|
||||
var visStart = cloneDate(start);
|
||||
var visEnd = cloneDate(end);
|
||||
var firstDay = opt('firstDay');
|
||||
var nwe = opt('weekends') ? 0 : 1;
|
||||
if (nwe) {
|
||||
skipWeekend(visStart);
|
||||
skipWeekend(visEnd, -1, true);
|
||||
}
|
||||
addDays(visStart, -((visStart.getDay() - Math.max(firstDay, nwe) + 7) % 7));
|
||||
addDays(visEnd, (7 - visEnd.getDay() + Math.max(firstDay, nwe)) % 7);
|
||||
var rowCnt = Math.round((visEnd - visStart) / (DAY_MS * 7));
|
||||
if (opt('weekMode') == 'fixed') {
|
||||
addDays(visEnd, (6 - rowCnt) * 7);
|
||||
rowCnt = 6;
|
||||
}
|
||||
t.title = formatDate(start, opt('titleFormat'));
|
||||
t.start = start;
|
||||
t.end = end;
|
||||
t.visStart = visStart;
|
||||
t.visEnd = visEnd;
|
||||
renderBasic(rowCnt, nwe ? 5 : 7, true);
|
||||
}
|
||||
|
||||
|
||||
}
|
43
src/common/CoordinateGrid.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
function CoordinateGrid(buildFunc) {
|
||||
|
||||
var t = this;
|
||||
var rows;
|
||||
var cols;
|
||||
|
||||
t.build = function() {
|
||||
rows = [];
|
||||
cols = [];
|
||||
buildFunc(rows, cols);
|
||||
};
|
||||
|
||||
t.cell = function(x, y) {
|
||||
var rowCnt = rows.length;
|
||||
var colCnt = cols.length;
|
||||
var i, r=-1, c=-1;
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
if (y >= rows[i][0] && y < rows[i][1]) {
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i=0; i<colCnt; i++) {
|
||||
if (x >= cols[i][0] && x < cols[i][1]) {
|
||||
c = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (r>=0 && c>=0) ? { row:r, col:c } : null;
|
||||
};
|
||||
|
||||
t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive
|
||||
var origin = originElement.offset();
|
||||
return {
|
||||
top: rows[row0][0] - origin.top,
|
||||
left: cols[col0][0] - origin.left,
|
||||
width: cols[col1][1] - cols[col0][0],
|
||||
height: rows[row1][1] - rows[row0][0]
|
||||
};
|
||||
};
|
||||
|
||||
}
|
232
src/common/DayEventRenderer.js
Normal file
|
@ -0,0 +1,232 @@
|
|||
|
||||
function DayEventRenderer() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderDaySegs = renderDaySegs;
|
||||
t.resizableDayEvent = resizableDayEvent;
|
||||
|
||||
|
||||
// imports
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var reportEventElement = t.reportEventElement;
|
||||
var showEvents = t.showEvents;
|
||||
var hideEvents = t.hideEvents;
|
||||
var eventResize = t.eventResize;
|
||||
var getRowCnt = t.getRowCnt;
|
||||
var getColCnt = t.getColCnt;
|
||||
var getColWidth = t.getColWidth;
|
||||
var allDayTR = t.allDayTR;
|
||||
var allDayBounds = t.allDayBounds;
|
||||
var colContentLeft = t.colContentLeft;
|
||||
var colContentRight = t.colContentRight;
|
||||
var dayOfWeekCol = t.dayOfWeekCol;
|
||||
var getDaySegmentContainer = t.getDaySegmentContainer;
|
||||
var bindDaySeg = t.bindDaySeg; //TODO: streamline this
|
||||
var formatDates = t.calendar.formatDates;
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function renderDaySegs(segs, modifiedEventId) {
|
||||
|
||||
var rtl=opt('isRTL'),
|
||||
i, segCnt=segs.length, seg,
|
||||
event,
|
||||
className,
|
||||
left, right,
|
||||
html='',
|
||||
eventElements,
|
||||
eventElement,
|
||||
triggerRes,
|
||||
hsideCache={},
|
||||
vmarginCache={},
|
||||
key, val,
|
||||
rowI, top, levelI, levelHeight,
|
||||
rowDivs=[],
|
||||
rowDivTops=[],
|
||||
bounds = allDayBounds(),
|
||||
minLeft = bounds.left,
|
||||
maxLeft = bounds.right,
|
||||
rowCnt = getRowCnt(),
|
||||
colCnt = getColCnt(),
|
||||
segmentContainer = getDaySegmentContainer();
|
||||
|
||||
// calculate desired position/dimensions, create html
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
event = seg.event;
|
||||
className = 'fc-event fc-event-hori ';
|
||||
if (rtl) {
|
||||
if (seg.isStart) {
|
||||
className += 'fc-corner-right ';
|
||||
}
|
||||
if (seg.isEnd) {
|
||||
className += 'fc-corner-left ';
|
||||
}
|
||||
left = seg.isEnd ? colContentLeft(dayOfWeekCol(seg.end.getDay()-1)) : minLeft;
|
||||
right = seg.isStart ? colContentRight(dayOfWeekCol(seg.start.getDay())) : maxLeft;
|
||||
}else{
|
||||
if (seg.isStart) {
|
||||
className += 'fc-corner-left ';
|
||||
}
|
||||
if (seg.isEnd) {
|
||||
className += 'fc-corner-right ';
|
||||
}
|
||||
left = seg.isStart ? colContentLeft(dayOfWeekCol(seg.start.getDay())) : minLeft;
|
||||
right = seg.isEnd ? colContentRight(dayOfWeekCol(seg.end.getDay()-1)) : maxLeft;
|
||||
}
|
||||
html +=
|
||||
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;left:"+left+"px'>" +
|
||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||
(!event.allDay && seg.isStart ?
|
||||
"<span class='fc-event-time'>" +
|
||||
htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
|
||||
"</span>"
|
||||
:'') +
|
||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||
"</a>" +
|
||||
((event.editable || event.editable === undefined && opt('editable')) && !opt('disableResizing') && $.fn.resizable ?
|
||||
"<div class='ui-resizable-handle ui-resizable-" + (rtl ? 'w' : 'e') + "'></div>"
|
||||
: '') +
|
||||
"</div>";
|
||||
seg.left = left;
|
||||
seg.outerWidth = right - left;
|
||||
}
|
||||
segmentContainer[0].innerHTML = html; // faster than html()
|
||||
eventElements = segmentContainer.children();
|
||||
|
||||
// retrieve elements, run through eventRender callback, bind handlers
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
eventElement = $(eventElements[i]); // faster than eq()
|
||||
event = seg.event;
|
||||
triggerRes = trigger('eventRender', event, event, eventElement);
|
||||
if (triggerRes === false) {
|
||||
eventElement.remove();
|
||||
}else{
|
||||
if (triggerRes && triggerRes !== true) {
|
||||
eventElement.remove();
|
||||
eventElement = $(triggerRes)
|
||||
.css({
|
||||
position: 'absolute',
|
||||
left: seg.left
|
||||
})
|
||||
.appendTo(segmentContainer);
|
||||
}
|
||||
seg.element = eventElement;
|
||||
if (event._id === modifiedEventId) {
|
||||
bindDaySeg(event, eventElement, seg);
|
||||
}else{
|
||||
eventElement[0]._fci = i; // for lazySegBind
|
||||
}
|
||||
reportEventElement(event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
lazySegBind(segmentContainer, segs, bindDaySeg);
|
||||
|
||||
// record event horizontal sides
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
val = hsideCache[key = seg.key = cssKey(eventElement[0])];
|
||||
seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
||||
}
|
||||
}
|
||||
|
||||
// set event widths
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
// record event heights
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
val = vmarginCache[key = seg.key];
|
||||
seg.outerHeight = eventElement[0].offsetHeight + (
|
||||
val === undefined ? (vmarginCache[key] = vmargins(eventElement[0])) : val
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// set row heights, calculate event tops (in relation to row top)
|
||||
for (i=0, rowI=0; rowI<rowCnt; rowI++) {
|
||||
top = levelI = levelHeight = 0;
|
||||
while (i<segCnt && (seg = segs[i]).row == rowI) {
|
||||
if (seg.level != levelI) {
|
||||
top += levelHeight;
|
||||
levelHeight = 0;
|
||||
levelI++;
|
||||
}
|
||||
levelHeight = Math.max(levelHeight, seg.outerHeight||0);
|
||||
seg.top = top;
|
||||
i++;
|
||||
}
|
||||
rowDivs[rowI] = allDayTR(rowI).find('td:first div.fc-day-content > div') // optimal selector?
|
||||
.height(top + levelHeight);
|
||||
}
|
||||
|
||||
// calculate row tops
|
||||
for (rowI=0; rowI<rowCnt; rowI++) {
|
||||
rowDivTops[rowI] = rowDivs[rowI][0].offsetTop;
|
||||
}
|
||||
|
||||
// set event tops
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
eventElement[0].style.top = rowDivTops[seg.row] + seg.top + 'px';
|
||||
event = seg.event;
|
||||
trigger('eventAfterRender', event, event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Resizing
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function resizableDayEvent(event, eventElement) {
|
||||
if (!opt('disableResizing') && eventElement.resizable) {
|
||||
var colWidth = getColWidth();
|
||||
eventElement.resizable({
|
||||
handles: opt('isRTL') ? {w:'div.ui-resizable-w'} : {e:'div.ui-resizable-e'},
|
||||
grid: colWidth,
|
||||
minWidth: colWidth/2, // need this or else IE throws errors when too small
|
||||
containment: t.element.parent().parent(), // the main element...
|
||||
// ... a fix. wouldn't allow extending to last column in agenda views (jq ui bug?)
|
||||
start: function(ev, ui) {
|
||||
eventElement.css('z-index', 9);
|
||||
hideEvents(event, eventElement);
|
||||
trigger('eventResizeStart', this, event, ev, ui);
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
trigger('eventResizeStop', this, event, ev, ui);
|
||||
// ui.size.width wasn't working with grid correctly, use .width()
|
||||
var dayDelta = Math.round((eventElement.width() - ui.originalSize.width) / colWidth);
|
||||
if (dayDelta) {
|
||||
eventResize(this, event, dayDelta, 0, ev, ui);
|
||||
}else{
|
||||
eventElement.css('z-index', 8);
|
||||
showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
27
src/common/HorizontalPositionCache.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
function HorizontalPositionCache(getElement) {
|
||||
|
||||
var t = this,
|
||||
elements = {},
|
||||
lefts = {},
|
||||
rights = {};
|
||||
|
||||
function e(i) {
|
||||
return elements[i] = elements[i] || getElement(i);
|
||||
}
|
||||
|
||||
t.left = function(i) {
|
||||
return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];
|
||||
};
|
||||
|
||||
t.right = function(i) {
|
||||
return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];
|
||||
};
|
||||
|
||||
t.clear = function() {
|
||||
elements = {};
|
||||
lefts = {};
|
||||
rights = {};
|
||||
};
|
||||
|
||||
}
|
44
src/common/HoverListener.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
function HoverListener(coordinateGrid) {
|
||||
|
||||
|
||||
var t = this;
|
||||
var bindType;
|
||||
var change;
|
||||
var firstCell;
|
||||
var cell;
|
||||
|
||||
|
||||
t.start = function(_change, ev, _bindType) {
|
||||
change = _change;
|
||||
firstCell = cell = null;
|
||||
coordinateGrid.build();
|
||||
mouse(ev);
|
||||
bindType = _bindType || 'mousemove';
|
||||
$(document).bind(bindType, mouse);
|
||||
};
|
||||
|
||||
|
||||
function mouse(ev) {
|
||||
var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
|
||||
if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
|
||||
if (newCell) {
|
||||
if (!firstCell) {
|
||||
firstCell = newCell;
|
||||
}
|
||||
change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);
|
||||
}else{
|
||||
change(newCell, firstCell);
|
||||
}
|
||||
cell = newCell;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
t.stop = function() {
|
||||
$(document).unbind(bindType, mouse);
|
||||
return cell;
|
||||
};
|
||||
|
||||
|
||||
}
|
37
src/common/OverlayManager.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
function OverlayManager() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.renderOverlay = renderOverlay;
|
||||
t.clearOverlays = clearOverlays;
|
||||
|
||||
|
||||
// locals
|
||||
var usedOverlays = [];
|
||||
var unusedOverlays = [];
|
||||
|
||||
|
||||
function renderOverlay(rect, parent) {
|
||||
var e = unusedOverlays.shift();
|
||||
if (!e) {
|
||||
e = $("<div class='fc-cell-overlay' style='position:absolute;z-index:3'/>");
|
||||
}
|
||||
if (e[0].parentNode != parent[0]) {
|
||||
e.appendTo(parent);
|
||||
}
|
||||
usedOverlays.push(e.css(rect).show());
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
function clearOverlays() {
|
||||
var e;
|
||||
while (e = usedOverlays.shift()) {
|
||||
unusedOverlays.push(e.hide().unbind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
98
src/common/SelectionManager.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
|
||||
//BUG: unselect needs to be triggered when events are dragged+dropped
|
||||
|
||||
function SelectionManager() {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.select = select;
|
||||
t.unselect = unselect;
|
||||
t.reportSelection = reportSelection;
|
||||
t.daySelectionMousedown = daySelectionMousedown;
|
||||
|
||||
|
||||
// imports
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var defaultSelectionEnd = t.defaultSelectionEnd;
|
||||
var renderSelection = t.renderSelection;
|
||||
var clearSelection = t.clearSelection;
|
||||
|
||||
|
||||
// locals
|
||||
var selected = false;
|
||||
|
||||
|
||||
|
||||
// unselectAuto
|
||||
if (opt('selectable') && opt('unselectAuto')) {
|
||||
$(document).mousedown(function(ev) {
|
||||
var ignore = opt('unselectCancel');
|
||||
if (ignore) {
|
||||
if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match
|
||||
return;
|
||||
}
|
||||
}
|
||||
unselect(ev);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function select(startDate, endDate, allDay) {
|
||||
unselect();
|
||||
if (!endDate) {
|
||||
endDate = defaultSelectionEnd(startDate, allDay);
|
||||
}
|
||||
renderSelection(startDate, endDate, allDay);
|
||||
reportSelection(startDate, endDate, allDay);
|
||||
}
|
||||
|
||||
|
||||
function unselect(ev) {
|
||||
if (selected) {
|
||||
selected = false;
|
||||
clearSelection();
|
||||
trigger('unselect', null, ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function reportSelection(startDate, endDate, allDay, ev) {
|
||||
selected = true;
|
||||
trigger('select', null, startDate, endDate, allDay, ev);
|
||||
}
|
||||
|
||||
|
||||
function daySelectionMousedown(ev) { // not really a generic manager method, oh well
|
||||
var cellDate = t.cellDate;
|
||||
var cellIsAllDay = t.cellIsAllDay;
|
||||
var hoverListener = t.getHoverListener();
|
||||
if (opt('selectable')) {
|
||||
unselect(ev);
|
||||
var _mousedownElement = this;
|
||||
var dates;
|
||||
hoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell
|
||||
clearSelection();
|
||||
if (cell && cellIsAllDay(cell)) {
|
||||
dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);
|
||||
renderSelection(dates[0], dates[1], true);
|
||||
}else{
|
||||
dates = null;
|
||||
}
|
||||
}, ev);
|
||||
$(document).one('mouseup', function(ev) {
|
||||
hoverListener.stop();
|
||||
if (dates) {
|
||||
if (+dates[0] == +dates[1]) {
|
||||
trigger('dayClick', _mousedownElement, dates[0], true, ev);
|
||||
// BUG: _mousedownElement will sometimes be the overlay
|
||||
}
|
||||
reportSelection(dates[0], dates[1], true, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
213
src/common/View.js
Normal file
|
@ -0,0 +1,213 @@
|
|||
|
||||
|
||||
function View(element, calendar, viewName) {
|
||||
var t = this;
|
||||
|
||||
|
||||
// exports
|
||||
t.element = element;
|
||||
t.calendar = calendar;
|
||||
t.name = viewName;
|
||||
t.opt = opt;
|
||||
t.trigger = trigger;
|
||||
t.reportEvents = reportEvents;
|
||||
t.clearEventData = clearEventData;
|
||||
t.eventEnd = eventEnd;
|
||||
t.reportEventElement = reportEventElement;
|
||||
t.eventElementHandlers = eventElementHandlers;
|
||||
t.showEvents = showEvents;
|
||||
t.hideEvents = hideEvents;
|
||||
t.eventDrop = eventDrop;
|
||||
t.eventResize = eventResize;
|
||||
// t.title
|
||||
// t.start, t.end
|
||||
// t.visStart, t.visEnd
|
||||
// t.eventsChanged // todo: maybe report to calendar instead
|
||||
|
||||
|
||||
// imports
|
||||
var defaultEventEnd = t.defaultEventEnd;
|
||||
var normalizeEvent = calendar.normalizeEvent; // in EventManager
|
||||
var rerenderEvents = calendar.rerenderEvents;
|
||||
|
||||
|
||||
// locals
|
||||
var eventsByID = {};
|
||||
var eventElements = [];
|
||||
var eventElementsByID = {};
|
||||
var options = calendar.options;
|
||||
|
||||
|
||||
|
||||
function opt(name, viewNameOverride) {
|
||||
var v = options[name];
|
||||
if (typeof v == 'object') {
|
||||
return smartProperty(v, viewNameOverride || viewName);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
function trigger(name, thisObj) {
|
||||
return calendar.trigger.apply(
|
||||
calendar,
|
||||
[name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Data
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// report when view receives new events
|
||||
function reportEvents(events) { // events are already normalized at this point
|
||||
eventsByID = {};
|
||||
var i, len=events.length, event;
|
||||
for (i=0; i<len; i++) {
|
||||
event = events[i];
|
||||
if (eventsByID[event._id]) {
|
||||
eventsByID[event._id].push(event);
|
||||
}else{
|
||||
eventsByID[event._id] = [event];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function clearEventData() { // todo: rename to clearReportedEvents or something
|
||||
eventElements = [];
|
||||
eventElementsByID = {};
|
||||
}
|
||||
|
||||
|
||||
// returns a Date object for an event's end
|
||||
function eventEnd(event) {
|
||||
return event.end ? cloneDate(event.end) : defaultEventEnd(event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Elements
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// report when view creates an element for an event
|
||||
function reportEventElement(event, element) {
|
||||
eventElements.push(element);
|
||||
if (eventElementsByID[event._id]) {
|
||||
eventElementsByID[event._id].push(element);
|
||||
}else{
|
||||
eventElementsByID[event._id] = [element];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// attaches eventClick, eventMouseover, eventMouseout
|
||||
function eventElementHandlers(event, eventElement) {
|
||||
eventElement
|
||||
.click(function(ev) {
|
||||
if (!eventElement.hasClass('ui-draggable-dragging') &&
|
||||
!eventElement.hasClass('ui-resizable-resizing')) {
|
||||
return trigger('eventClick', this, event, ev);
|
||||
}
|
||||
})
|
||||
.hover(
|
||||
function(ev) {
|
||||
trigger('eventMouseover', this, event, ev);
|
||||
},
|
||||
function(ev) {
|
||||
trigger('eventMouseout', this, event, ev);
|
||||
}
|
||||
);
|
||||
// TODO: don't fire eventMouseover/eventMouseout *while* dragging is occuring (on subject element)
|
||||
// TODO: same for resizing
|
||||
}
|
||||
|
||||
|
||||
function showEvents(event, exceptElement) {
|
||||
eachEventElement(event, exceptElement, 'show');
|
||||
}
|
||||
|
||||
|
||||
function hideEvents(event, exceptElement) {
|
||||
eachEventElement(event, exceptElement, 'hide');
|
||||
}
|
||||
|
||||
|
||||
function eachEventElement(event, exceptElement, funcName) {
|
||||
var elements = eventElementsByID[event._id],
|
||||
i, len = elements.length;
|
||||
for (i=0; i<len; i++) {
|
||||
if (elements[i][0] != exceptElement[0]) {
|
||||
elements[i][funcName]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Modification Reporting
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
|
||||
var oldAllDay = event.allDay;
|
||||
var eventId = event._id;
|
||||
moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
|
||||
trigger('eventDrop', e, event, dayDelta, minuteDelta, allDay, function() {
|
||||
// TODO: investigate cases where this inverse technique might not work
|
||||
moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
|
||||
rerenderEvents();
|
||||
}, ev, ui);
|
||||
t.eventsChanged = true;
|
||||
rerenderEvents(eventId);
|
||||
}
|
||||
|
||||
|
||||
function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
|
||||
var eventId = event._id;
|
||||
elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
|
||||
trigger('eventResize', e, event, dayDelta, minuteDelta, function() {
|
||||
// TODO: investigate cases where this inverse technique might not work
|
||||
elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
|
||||
rerenderEvents();
|
||||
}, ev, ui);
|
||||
t.eventsChanged = true;
|
||||
rerenderEvents(eventId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Modification Math
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function moveEvents(events, dayDelta, minuteDelta, allDay) {
|
||||
minuteDelta = minuteDelta || 0;
|
||||
for (var e, len=events.length, i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
if (allDay !== undefined) {
|
||||
e.allDay = allDay;
|
||||
}
|
||||
addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
|
||||
if (e.end) {
|
||||
e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
|
||||
}
|
||||
normalizeEvent(e, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function elongateEvents(events, dayDelta, minuteDelta) {
|
||||
minuteDelta = minuteDelta || 0;
|
||||
for (var e, len=events.length, i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
e.end = addMinutes(addDays(eventEnd(e), dayDelta, true), minuteDelta);
|
||||
normalizeEvent(e, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
129
src/common/common.css
Normal file
|
@ -0,0 +1,129 @@
|
|||
|
||||
|
||||
/* Global Event Styles
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event,
|
||||
.fc-agenda .fc-event-time,
|
||||
.fc-event a {
|
||||
border-style: solid;
|
||||
border-color: #36c; /* default BORDER color (probably the same as background-color) */
|
||||
background-color: #36c; /* default BACKGROUND color */
|
||||
color: #fff; /* default TEXT color */
|
||||
}
|
||||
|
||||
/* Use the 'className' CalEvent property and the following
|
||||
* example CSS to change event color on a per-event basis:
|
||||
*
|
||||
* .myclass,
|
||||
* .fc-agenda .myclass .fc-event-time,
|
||||
* .myclass a {
|
||||
* background-color: black;
|
||||
* border-color: black;
|
||||
* color: red;
|
||||
* }
|
||||
*/
|
||||
|
||||
.fc-event {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.fc-event a {
|
||||
overflow: hidden;
|
||||
font-size: .85em;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-event-editable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-event-time,
|
||||
.fc-event-title {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
/* for fake rounded corners */
|
||||
|
||||
.fc-event a {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* right-to-left */
|
||||
|
||||
.fc-rtl .fc-event a {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* resizable */
|
||||
|
||||
.fc .ui-resizable-handle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
border: 0 !important; /* important overrides pre jquery ui 1.7 styles */
|
||||
background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Horizontal Events
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event-hori {
|
||||
border-width: 1px 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.fc-event-hori a {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* for fake rounded corners */
|
||||
|
||||
.fc-content .fc-corner-left {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-left a {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-right {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-right a {
|
||||
margin-right: -1px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
/* resizable */
|
||||
|
||||
.fc-event-hori .ui-resizable-e {
|
||||
top: 0 !important; /* importants override pre jquery ui 1.7 styles */
|
||||
right: -3px !important;
|
||||
width: 7px !important;
|
||||
height: 100% !important;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.fc-event-hori .ui-resizable-w {
|
||||
top: 0 !important;
|
||||
left: -3px !important;
|
||||
width: 7px !important;
|
||||
height: 100% !important;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.fc-event-hori .ui-resizable-handle {
|
||||
_padding-bottom: 14px; /* IE6 had 0 height */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,11 +1,24 @@
|
|||
|
||||
|
||||
fc.addDays = addDays;
|
||||
fc.cloneDate = cloneDate;
|
||||
fc.parseDate = parseDate;
|
||||
fc.parseISO8601 = parseISO8601;
|
||||
fc.parseTime = parseTime;
|
||||
fc.formatDate = formatDate;
|
||||
fc.formatDates = formatDates;
|
||||
|
||||
|
||||
|
||||
/* Date Math
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var DAY_MS = 86400000,
|
||||
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
|
||||
DAY_MS = 86400000,
|
||||
HOUR_MS = 3600000,
|
||||
MINUTE_MS = 60000;
|
||||
|
||||
|
||||
function addYears(d, n, keepTime) {
|
||||
d.setFullYear(d.getFullYear() + n);
|
||||
if (!keepTime) {
|
||||
|
@ -14,6 +27,7 @@ function addYears(d, n, keepTime) {
|
|||
return d;
|
||||
}
|
||||
|
||||
|
||||
function addMonths(d, n, keepTime) { // prevents day overflow/underflow
|
||||
if (+d) { // prevent infinite looping on invalid dates
|
||||
var m = d.getMonth() + n,
|
||||
|
@ -31,6 +45,7 @@ function addMonths(d, n, keepTime) { // prevents day overflow/underflow
|
|||
return d;
|
||||
}
|
||||
|
||||
|
||||
function addDays(d, n, keepTime) { // deals with daylight savings
|
||||
if (+d) {
|
||||
var dd = d.getDate() + n,
|
||||
|
@ -45,7 +60,7 @@ function addDays(d, n, keepTime) { // deals with daylight savings
|
|||
}
|
||||
return d;
|
||||
}
|
||||
fc.addDays = addDays;
|
||||
|
||||
|
||||
function fixDate(d, check) { // force d to be on check's YMD, for daylight savings purposes
|
||||
if (+d) { // prevent infinite looping on invalid dates
|
||||
|
@ -55,11 +70,13 @@ function fixDate(d, check) { // force d to be on check's YMD, for daylight savin
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function addMinutes(d, n) {
|
||||
d.setMinutes(d.getMinutes() + n);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
function clearTime(d) {
|
||||
d.setHours(0);
|
||||
d.setMinutes(0);
|
||||
|
@ -68,13 +85,14 @@ function clearTime(d) {
|
|||
return d;
|
||||
}
|
||||
|
||||
|
||||
function cloneDate(d, dontKeepTime) {
|
||||
if (dontKeepTime) {
|
||||
return clearTime(new Date(+d));
|
||||
}
|
||||
return new Date(+d);
|
||||
}
|
||||
fc.cloneDate = cloneDate;
|
||||
|
||||
|
||||
function zeroDate() { // returns a Date with time 00:00:00 and dateOfMonth=1
|
||||
var i=0, d;
|
||||
|
@ -84,6 +102,7 @@ function zeroDate() { // returns a Date with time 00:00:00 and dateOfMonth=1
|
|||
return d;
|
||||
}
|
||||
|
||||
|
||||
function skipWeekend(date, inc, excl) {
|
||||
inc = inc || 1;
|
||||
while (!date.getDay() || (excl && date.getDay()==1 || !excl && date.getDay()==6)) {
|
||||
|
@ -92,10 +111,12 @@ function skipWeekend(date, inc, excl) {
|
|||
return date;
|
||||
}
|
||||
|
||||
|
||||
function dayDiff(d1, d2) { // d1 - d2
|
||||
return Math.round((cloneDate(d1, true) - cloneDate(d2, true)) / DAY_MS);
|
||||
}
|
||||
|
||||
|
||||
function setYMD(date, y, m, d) {
|
||||
if (y !== undefined && y != date.getFullYear()) {
|
||||
date.setDate(1);
|
||||
|
@ -116,7 +137,8 @@ function setYMD(date, y, m, d) {
|
|||
/* Date Parsing
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var parseDate = fc.parseDate = function(s) {
|
||||
|
||||
function parseDate(s) {
|
||||
if (typeof s == 'object') { // already a Date object
|
||||
return s;
|
||||
}
|
||||
|
@ -131,9 +153,10 @@ var parseDate = fc.parseDate = function(s) {
|
|||
}
|
||||
// TODO: never return invalid dates (like from new Date(<string>)), return null instead
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
var parseISO8601 = fc.parseISO8601 = function(s, ignoreTimezone) {
|
||||
|
||||
function parseISO8601(s, ignoreTimezone) {
|
||||
// derived from http://delete.me.uk/2005/03/iso8601.html
|
||||
// TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html
|
||||
var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/);
|
||||
|
@ -173,9 +196,10 @@ var parseISO8601 = fc.parseISO8601 = function(s, ignoreTimezone) {
|
|||
offset -= date.getTimezoneOffset();
|
||||
}
|
||||
return new Date(+date + (offset * 60 * 1000));
|
||||
};
|
||||
}
|
||||
|
||||
var parseTime = fc.parseTime = function(s) { // returns minutes since start of day
|
||||
|
||||
function parseTime(s) { // returns minutes since start of day
|
||||
if (typeof s == 'number') { // an hour
|
||||
return s * 60;
|
||||
}
|
||||
|
@ -193,18 +217,21 @@ var parseTime = fc.parseTime = function(s) { // returns minutes since start of d
|
|||
}
|
||||
return h * 60 + (m[2] ? parseInt(m[2]) : 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Date Formatting
|
||||
-----------------------------------------------------------------------------*/
|
||||
// TODO: use same function formatDate(date, [date2], format, [options])
|
||||
|
||||
var formatDate = fc.formatDate = function(date, format, options) {
|
||||
|
||||
function formatDate(date, format, options) {
|
||||
return formatDates(date, null, format, options);
|
||||
};
|
||||
}
|
||||
|
||||
var formatDates = fc.formatDates = function(date1, date2, format, options) {
|
||||
|
||||
function formatDates(date1, date2, format, options) {
|
||||
options = options || defaults;
|
||||
var date = date1,
|
||||
otherDate = date2,
|
||||
|
@ -281,6 +308,7 @@ var formatDates = fc.formatDates = function(date1, date2, format, options) {
|
|||
return res;
|
||||
};
|
||||
|
||||
|
||||
var dateFormatters = {
|
||||
s : function(d) { return d.getSeconds() },
|
||||
ss : function(d) { return zeroPad(d.getSeconds()) },
|
||||
|
@ -315,282 +343,3 @@ var dateFormatters = {
|
|||
};
|
||||
|
||||
|
||||
|
||||
/* Element Dimensions
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
function setOuterWidth(element, width, includeMargins) {
|
||||
element.each(function(i, _element) {
|
||||
_element.style.width = width - hsides(_element, includeMargins) + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
function setOuterHeight(element, height, includeMargins) {
|
||||
element.each(function(i, _element) {
|
||||
_element.style.height = height - vsides(_element, includeMargins) + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function hsides(_element, includeMargins) {
|
||||
return (parseFloat(jQuery.curCSS(_element, 'paddingLeft', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'paddingRight', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'borderLeftWidth', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'borderRightWidth', true)) || 0) +
|
||||
(includeMargins ? hmargins(_element) : 0);
|
||||
}
|
||||
|
||||
function hmargins(_element) {
|
||||
return (parseFloat(jQuery.curCSS(_element, 'marginLeft', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'marginRight', true)) || 0);
|
||||
}
|
||||
|
||||
function vsides(_element, includeMargins) {
|
||||
return (parseFloat(jQuery.curCSS(_element, 'paddingTop', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'paddingBottom', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'borderTopWidth', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'borderBottomWidth', true)) || 0) +
|
||||
(includeMargins ? vmargins(_element) : 0);
|
||||
}
|
||||
|
||||
function vmargins(_element) {
|
||||
return (parseFloat(jQuery.curCSS(_element, 'marginTop', true)) || 0) +
|
||||
(parseFloat(jQuery.curCSS(_element, 'marginBottom', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function setMinHeight(element, h) {
|
||||
h = typeof h == 'number' ? h + 'px' : h;
|
||||
element[0].style.cssText += ';min-height:' + h + ';_height:' + h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Position Calculation
|
||||
-----------------------------------------------------------------------------*/
|
||||
// nasty bugs in opera 9.25
|
||||
// position()'s top returning incorrectly with TR/TD or elements within TD
|
||||
|
||||
var topBug;
|
||||
|
||||
function topCorrect(tr) { // tr/th/td or anything else
|
||||
if (topBug !== false) {
|
||||
var cell;
|
||||
if (tr.is('th,td')) {
|
||||
tr = (cell = tr).parent();
|
||||
}
|
||||
if (topBug === undefined && tr.is('tr')) {
|
||||
topBug = tr.position().top != tr.children().position().top;
|
||||
}
|
||||
if (topBug) {
|
||||
return tr.parent().position().top + (cell ? tr.position().top - cell.position().top : 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Coordinate Grid
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
function CoordinateGrid(buildFunc) {
|
||||
|
||||
var t = this;
|
||||
var rows;
|
||||
var cols;
|
||||
|
||||
t.build = function() {
|
||||
rows = [];
|
||||
cols = [];
|
||||
buildFunc(rows, cols);
|
||||
};
|
||||
|
||||
t.cell = function(x, y) {
|
||||
var rowCnt = rows.length;
|
||||
var colCnt = cols.length;
|
||||
var i, r=-1, c=-1;
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
if (y >= rows[i][0] && y < rows[i][1]) {
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i=0; i<colCnt; i++) {
|
||||
if (x >= cols[i][0] && x < cols[i][1]) {
|
||||
c = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (r>=0 && c>=0) ? { row:r, col:c } : null;
|
||||
};
|
||||
|
||||
t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive
|
||||
var origin = originElement.offset();
|
||||
return {
|
||||
top: rows[row0][0] - origin.top,
|
||||
left: cols[col0][0] - origin.left,
|
||||
width: cols[col1][1] - cols[col0][0],
|
||||
height: rows[row1][1] - rows[row0][0]
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Hover Listener
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
function HoverListener(coordinateGrid) {
|
||||
|
||||
var t = this;
|
||||
var bindType;
|
||||
var change;
|
||||
var firstCell;
|
||||
var cell;
|
||||
|
||||
t.start = function(_change, ev, _bindType) {
|
||||
change = _change;
|
||||
firstCell = cell = null;
|
||||
coordinateGrid.build();
|
||||
mouse(ev);
|
||||
bindType = _bindType || 'mousemove';
|
||||
$(document).bind(bindType, mouse);
|
||||
};
|
||||
|
||||
function mouse(ev) {
|
||||
var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
|
||||
if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
|
||||
if (newCell) {
|
||||
if (!firstCell) {
|
||||
firstCell = newCell;
|
||||
}
|
||||
change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);
|
||||
}else{
|
||||
change(newCell, firstCell);
|
||||
}
|
||||
cell = newCell;
|
||||
}
|
||||
}
|
||||
|
||||
t.stop = function() {
|
||||
$(document).unbind(bindType, mouse);
|
||||
return cell;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Misc Utils
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||
|
||||
function zeroPad(n) {
|
||||
return (n < 10 ? '0' : '') + n;
|
||||
}
|
||||
|
||||
function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
|
||||
if (obj[name] !== undefined) {
|
||||
return obj[name];
|
||||
}
|
||||
var parts = name.split(/(?=[A-Z])/),
|
||||
i=parts.length-1, res;
|
||||
for (; i>=0; i--) {
|
||||
res = obj[parts[i].toLowerCase()];
|
||||
if (res !== undefined) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return obj[''];
|
||||
}
|
||||
|
||||
function htmlEscape(s) {
|
||||
return s.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/\n/g, '<br />');
|
||||
}
|
||||
|
||||
|
||||
|
||||
function HorizontalPositionCache(getElement) {
|
||||
|
||||
var t = this,
|
||||
elements = {},
|
||||
lefts = {},
|
||||
rights = {};
|
||||
|
||||
function e(i) {
|
||||
return elements[i] = elements[i] || getElement(i);
|
||||
}
|
||||
|
||||
t.left = function(i) {
|
||||
return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];
|
||||
};
|
||||
|
||||
t.right = function(i) {
|
||||
return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];
|
||||
};
|
||||
|
||||
t.clear = function() {
|
||||
elements = {};
|
||||
lefts = {};
|
||||
rights = {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function cssKey(_element) {
|
||||
return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
function cmp(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function exclEndDay(event) {
|
||||
if (event.end) {
|
||||
return _exclEndDay(event.end, event.allDay);
|
||||
}else{
|
||||
return addDays(cloneDate(event.start), 1);
|
||||
}
|
||||
}
|
||||
|
||||
function _exclEndDay(end, allDay) {
|
||||
end = cloneDate(end);
|
||||
return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function disableTextSelection(element) {
|
||||
element
|
||||
.attr('unselectable', 'on')
|
||||
.css('MozUserSelect', 'none')
|
||||
.bind('selectstart.ui', function() { return false; });
|
||||
}
|
||||
|
||||
/*
|
||||
function enableTextSelection(element) {
|
||||
element
|
||||
.attr('unselectable', 'off')
|
||||
.css('MozUserSelect', '')
|
||||
.unbind('selectstart.ui');
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
285
src/common/util.js
Normal file
|
@ -0,0 +1,285 @@
|
|||
|
||||
|
||||
/* Event Date Math
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function exclEndDay(event) {
|
||||
if (event.end) {
|
||||
return _exclEndDay(event.end, event.allDay);
|
||||
}else{
|
||||
return addDays(cloneDate(event.start), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _exclEndDay(end, allDay) {
|
||||
end = cloneDate(end);
|
||||
return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
|
||||
}
|
||||
|
||||
|
||||
function segCmp(a, b) {
|
||||
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
||||
}
|
||||
|
||||
|
||||
function segsCollide(seg1, seg2) {
|
||||
return seg1.end > seg2.start && seg1.start < seg2.end;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Sorting
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// event rendering utilities
|
||||
function sliceSegs(events, visEventEnds, start, end) {
|
||||
var segs = [],
|
||||
i, len=events.length, event,
|
||||
eventStart, eventEnd,
|
||||
segStart, segEnd,
|
||||
isStart, isEnd;
|
||||
for (i=0; i<len; i++) {
|
||||
event = events[i];
|
||||
eventStart = event.start;
|
||||
eventEnd = visEventEnds[i];
|
||||
if (eventEnd > start && eventStart < end) {
|
||||
if (eventStart < start) {
|
||||
segStart = cloneDate(start);
|
||||
isStart = false;
|
||||
}else{
|
||||
segStart = eventStart;
|
||||
isStart = true;
|
||||
}
|
||||
if (eventEnd > end) {
|
||||
segEnd = cloneDate(end);
|
||||
isEnd = false;
|
||||
}else{
|
||||
segEnd = eventEnd;
|
||||
isEnd = true;
|
||||
}
|
||||
segs.push({
|
||||
event: event,
|
||||
start: segStart,
|
||||
end: segEnd,
|
||||
isStart: isStart,
|
||||
isEnd: isEnd,
|
||||
msLength: segEnd - segStart
|
||||
});
|
||||
}
|
||||
}
|
||||
return segs.sort(segCmp);
|
||||
}
|
||||
|
||||
|
||||
// event rendering calculation utilities
|
||||
function stackSegs(segs) {
|
||||
var levels = [],
|
||||
i, len = segs.length, seg,
|
||||
j, collide, k;
|
||||
for (i=0; i<len; i++) {
|
||||
seg = segs[i];
|
||||
j = 0; // the level index where seg should belong
|
||||
while (true) {
|
||||
collide = false;
|
||||
if (levels[j]) {
|
||||
for (k=0; k<levels[j].length; k++) {
|
||||
if (segsCollide(levels[j][k], seg)) {
|
||||
collide = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (collide) {
|
||||
j++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (levels[j]) {
|
||||
levels[j].push(seg);
|
||||
}else{
|
||||
levels[j] = [seg];
|
||||
}
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Element Binding
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function lazySegBind(container, segs, bindHandlers) {
|
||||
container.unbind('mouseover').mouseover(function(ev) {
|
||||
var parent=ev.target, e,
|
||||
i, seg;
|
||||
while (parent != this) {
|
||||
e = parent;
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
if ((i = e._fci) !== undefined) {
|
||||
e._fci = undefined;
|
||||
seg = segs[i];
|
||||
bindHandlers(seg.event, seg.element, seg);
|
||||
$(ev.target).trigger(ev);
|
||||
}
|
||||
ev.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Element Dimensions
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function setOuterWidth(element, width, includeMargins) {
|
||||
element.each(function(i, _element) {
|
||||
_element.style.width = width - hsides(_element, includeMargins) + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function setOuterHeight(element, height, includeMargins) {
|
||||
element.each(function(i, _element) {
|
||||
_element.style.height = height - vsides(_element, includeMargins) + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function hsides(_element, includeMargins) {
|
||||
return (parseFloat($.curCSS(_element, 'paddingLeft', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'paddingRight', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'borderLeftWidth', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'borderRightWidth', true)) || 0) +
|
||||
(includeMargins ? hmargins(_element) : 0);
|
||||
}
|
||||
|
||||
|
||||
function hmargins(_element) {
|
||||
return (parseFloat($.curCSS(_element, 'marginLeft', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'marginRight', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function vsides(_element, includeMargins) {
|
||||
return (parseFloat($.curCSS(_element, 'paddingTop', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'paddingBottom', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'borderTopWidth', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'borderBottomWidth', true)) || 0) +
|
||||
(includeMargins ? vmargins(_element) : 0);
|
||||
}
|
||||
|
||||
|
||||
function vmargins(_element) {
|
||||
return (parseFloat($.curCSS(_element, 'marginTop', true)) || 0) +
|
||||
(parseFloat($.curCSS(_element, 'marginBottom', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function setMinHeight(element, h) {
|
||||
h = typeof h == 'number' ? h + 'px' : h;
|
||||
element[0].style.cssText += ';min-height:' + h + ';_height:' + h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Position Calculation
|
||||
-----------------------------------------------------------------------------*/
|
||||
// nasty bugs in opera 9.25
|
||||
// position()'s top returning incorrectly with TR/TD or elements within TD
|
||||
|
||||
var topBug;
|
||||
|
||||
function topCorrect(tr) { // tr/th/td or anything else
|
||||
if (topBug !== false) {
|
||||
var cell;
|
||||
if (tr.is('th,td')) {
|
||||
tr = (cell = tr).parent();
|
||||
}
|
||||
if (topBug === undefined && tr.is('tr')) {
|
||||
topBug = tr.position().top != tr.children().position().top;
|
||||
}
|
||||
if (topBug) {
|
||||
return tr.parent().position().top + (cell ? tr.position().top - cell.position().top : 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Misc Utils
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
//TODO: arraySlice
|
||||
//TODO: isFunction, grep ?
|
||||
|
||||
|
||||
function noop() { }
|
||||
|
||||
|
||||
function cmp(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
|
||||
function zeroPad(n) {
|
||||
return (n < 10 ? '0' : '') + n;
|
||||
}
|
||||
|
||||
|
||||
function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
|
||||
if (obj[name] !== undefined) {
|
||||
return obj[name];
|
||||
}
|
||||
var parts = name.split(/(?=[A-Z])/),
|
||||
i=parts.length-1, res;
|
||||
for (; i>=0; i--) {
|
||||
res = obj[parts[i].toLowerCase()];
|
||||
if (res !== undefined) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return obj[''];
|
||||
}
|
||||
|
||||
|
||||
function htmlEscape(s) {
|
||||
return s.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/\n/g, '<br />');
|
||||
}
|
||||
|
||||
|
||||
function cssKey(_element) {
|
||||
return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
|
||||
}
|
||||
|
||||
|
||||
function disableTextSelection(element) {
|
||||
element
|
||||
.attr('unselectable', 'on')
|
||||
.css('MozUserSelect', 'none')
|
||||
.bind('selectstart.ui', function() { return false; });
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
function enableTextSelection(element) {
|
||||
element
|
||||
.attr('unselectable', 'off')
|
||||
.css('MozUserSelect', '')
|
||||
.unbind('selectstart.ui');
|
||||
}
|
||||
*/
|
||||
|
||||
|
92
src/defaults.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
|
||||
var defaults = {
|
||||
|
||||
// display
|
||||
defaultView: 'month',
|
||||
aspectRatio: 1.35,
|
||||
header: {
|
||||
left: 'title',
|
||||
center: '',
|
||||
right: 'today prev,next'
|
||||
},
|
||||
weekends: true,
|
||||
|
||||
// editing
|
||||
//editable: false,
|
||||
//disableDragging: false,
|
||||
//disableResizing: false,
|
||||
|
||||
allDayDefault: true,
|
||||
|
||||
// event ajax
|
||||
lazyFetching: true,
|
||||
startParam: 'start',
|
||||
endParam: 'end',
|
||||
|
||||
// time formats
|
||||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
|
||||
day: 'dddd, MMM d, yyyy'
|
||||
},
|
||||
columnFormat: {
|
||||
month: 'ddd',
|
||||
week: 'ddd M/d',
|
||||
day: 'dddd M/d'
|
||||
},
|
||||
timeFormat: { // for event elements
|
||||
'': 'h(:mm)t' // default
|
||||
},
|
||||
|
||||
// locale
|
||||
isRTL: false,
|
||||
firstDay: 0,
|
||||
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||
monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||
dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
||||
buttonText: {
|
||||
prev: ' ◄ ',
|
||||
next: ' ► ',
|
||||
prevYear: ' << ',
|
||||
nextYear: ' >> ',
|
||||
today: 'today',
|
||||
month: 'month',
|
||||
week: 'week',
|
||||
day: 'day'
|
||||
},
|
||||
|
||||
// jquery-ui theming
|
||||
theme: false,
|
||||
buttonIcons: {
|
||||
prev: 'circle-triangle-w',
|
||||
next: 'circle-triangle-e'
|
||||
},
|
||||
|
||||
//selectable: false,
|
||||
unselectAuto: true,
|
||||
|
||||
dropAccept: '*'
|
||||
|
||||
};
|
||||
|
||||
// right-to-left defaults
|
||||
var rtlDefaults = {
|
||||
header: {
|
||||
left: 'next,prev today',
|
||||
center: '',
|
||||
right: 'title'
|
||||
},
|
||||
buttonText: {
|
||||
prev: ' ► ',
|
||||
next: ' ◄ ',
|
||||
prevYear: ' >> ',
|
||||
nextYear: ' << '
|
||||
},
|
||||
buttonIcons: {
|
||||
prev: 'circle-triangle-e',
|
||||
next: 'circle-triangle-w'
|
||||
}
|
||||
};
|
||||
|
||||
|
6
src/gcal/_loader.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
startload();
|
||||
|
||||
js('gcal.js');
|
||||
|
||||
endload();
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* FullCalendar v@VERSION Google Calendar Extension
|
||||
*
|
||||
* Copyright (c) 2009 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
* Copyright (c) 2010 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: @DATE
|
||||
*
|
792
src/grid.js
|
@ -1,792 +0,0 @@
|
|||
|
||||
/* Grid-based Views: month, basicWeek, basicDay
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
setDefaults({
|
||||
weekMode: 'fixed'
|
||||
});
|
||||
|
||||
views.month = function(element, options, viewName) {
|
||||
return new Grid(element, options, {
|
||||
render: function(date, delta) {
|
||||
if (delta) {
|
||||
addMonths(date, delta);
|
||||
date.setDate(1);
|
||||
}
|
||||
// start/end
|
||||
var start = this.start = cloneDate(date, true);
|
||||
start.setDate(1);
|
||||
this.end = addMonths(cloneDate(start), 1);
|
||||
// visStart/visEnd
|
||||
var visStart = this.visStart = cloneDate(start),
|
||||
visEnd = this.visEnd = cloneDate(this.end),
|
||||
nwe = options.weekends ? 0 : 1;
|
||||
if (nwe) {
|
||||
skipWeekend(visStart);
|
||||
skipWeekend(visEnd, -1, true);
|
||||
}
|
||||
addDays(visStart, -((visStart.getDay() - Math.max(options.firstDay, nwe) + 7) % 7));
|
||||
addDays(visEnd, (7 - visEnd.getDay() + Math.max(options.firstDay, nwe)) % 7);
|
||||
// row count
|
||||
var rowCnt = Math.round((visEnd - visStart) / (DAY_MS * 7));
|
||||
if (options.weekMode == 'fixed') {
|
||||
addDays(visEnd, (6 - rowCnt) * 7);
|
||||
rowCnt = 6;
|
||||
}
|
||||
// title
|
||||
this.title = formatDate(
|
||||
start,
|
||||
this.option('titleFormat'),
|
||||
options
|
||||
);
|
||||
// render
|
||||
this.renderGrid(
|
||||
rowCnt, options.weekends ? 7 : 5,
|
||||
this.option('columnFormat'),
|
||||
true
|
||||
);
|
||||
}
|
||||
}, viewName);
|
||||
};
|
||||
|
||||
views.basicWeek = function(element, options, viewName) {
|
||||
return new Grid(element, options, {
|
||||
render: function(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta * 7);
|
||||
}
|
||||
var visStart = this.visStart = cloneDate(
|
||||
this.start = addDays(cloneDate(date), -((date.getDay() - options.firstDay + 7) % 7))
|
||||
),
|
||||
visEnd = this.visEnd = cloneDate(
|
||||
this.end = addDays(cloneDate(visStart), 7)
|
||||
);
|
||||
if (!options.weekends) {
|
||||
skipWeekend(visStart);
|
||||
skipWeekend(visEnd, -1, true);
|
||||
}
|
||||
this.title = formatDates(
|
||||
visStart,
|
||||
addDays(cloneDate(visEnd), -1),
|
||||
this.option('titleFormat'),
|
||||
options
|
||||
);
|
||||
this.renderGrid(
|
||||
1, options.weekends ? 7 : 5,
|
||||
this.option('columnFormat'),
|
||||
false
|
||||
);
|
||||
}
|
||||
}, viewName);
|
||||
};
|
||||
|
||||
views.basicDay = function(element, options, viewName) {
|
||||
return new Grid(element, options, {
|
||||
render: function(date, delta) {
|
||||
if (delta) {
|
||||
addDays(date, delta);
|
||||
if (!options.weekends) {
|
||||
skipWeekend(date, delta < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
this.title = formatDate(date, this.option('titleFormat'), options);
|
||||
this.start = this.visStart = cloneDate(date, true);
|
||||
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
||||
this.renderGrid(
|
||||
1, 1,
|
||||
this.option('columnFormat'),
|
||||
false
|
||||
);
|
||||
}
|
||||
}, viewName);
|
||||
};
|
||||
|
||||
|
||||
// rendering bugs
|
||||
|
||||
var tdHeightBug;
|
||||
|
||||
|
||||
function Grid(element, options, methods, viewName) {
|
||||
|
||||
var tm, firstDay,
|
||||
nwe, // no weekends (int)
|
||||
rtl, dis, dit, // day index sign / translate
|
||||
viewWidth, viewHeight,
|
||||
rowCnt, colCnt,
|
||||
colWidth,
|
||||
thead, tbody,
|
||||
cachedEvents=[],
|
||||
segmentContainer,
|
||||
dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) {
|
||||
return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div');
|
||||
}),
|
||||
// ...
|
||||
|
||||
// initialize superclass
|
||||
view = $.extend(this, viewMethods, methods, {
|
||||
renderGrid: renderGrid,
|
||||
renderEvents: renderEvents,
|
||||
rerenderEvents: rerenderEvents,
|
||||
clearEvents: clearEvents,
|
||||
setHeight: setHeight,
|
||||
setWidth: setWidth,
|
||||
defaultEventEnd: function(event) { // calculates an end if event doesnt have one, mostly for resizing
|
||||
return cloneDate(event.start);
|
||||
}
|
||||
});
|
||||
view.name = viewName;
|
||||
view.init(element, options);
|
||||
|
||||
|
||||
|
||||
/* Grid Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
disableTextSelection(element.addClass('fc-grid'));
|
||||
|
||||
|
||||
function renderGrid(r, c, colFormat, showNumbers) {
|
||||
|
||||
rowCnt = r;
|
||||
colCnt = c;
|
||||
|
||||
// update option-derived variables
|
||||
tm = options.theme ? 'ui' : 'fc';
|
||||
nwe = options.weekends ? 0 : 1;
|
||||
firstDay = options.firstDay;
|
||||
if (rtl = options.isRTL) {
|
||||
dis = -1;
|
||||
dit = colCnt - 1;
|
||||
}else{
|
||||
dis = 1;
|
||||
dit = 0;
|
||||
}
|
||||
|
||||
var month = view.start.getMonth(),
|
||||
today = clearTime(new Date()),
|
||||
s, i, j, d = cloneDate(view.visStart);
|
||||
|
||||
if (!tbody) { // first time, build all cells from scratch
|
||||
|
||||
var table = $("<table/>").appendTo(element);
|
||||
|
||||
s = "<thead><tr>";
|
||||
for (i=0; i<colCnt; i++) {
|
||||
s += "<th class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default' +
|
||||
(i==dit ? ' fc-leftmost' : '') +
|
||||
"'>" + formatDate(d, colFormat, options) + "</th>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
thead = $(s + "</tr></thead>").appendTo(table);
|
||||
|
||||
s = "<tbody>";
|
||||
d = cloneDate(view.visStart);
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
s += "<tr class='fc-week" + i + "'>";
|
||||
for (j=0; j<colCnt; j++) {
|
||||
s += "<td class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default fc-day' + (i*colCnt+j) +
|
||||
(j==dit ? ' fc-leftmost' : '') +
|
||||
(rowCnt>1 && d.getMonth() != month ? ' fc-other-month' : '') +
|
||||
(+d == +today ?
|
||||
' fc-today '+tm+'-state-highlight' :
|
||||
' fc-not-today') + "'>" +
|
||||
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
|
||||
"<div class='fc-day-content'><div style='position:relative'> </div></div></td>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
s += "</tr>";
|
||||
}
|
||||
tbody = $(s + "</tbody>").appendTo(table);
|
||||
dayBind(tbody.find('td'));
|
||||
|
||||
segmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(element);
|
||||
|
||||
}else{ // NOT first time, reuse as many cells as possible
|
||||
|
||||
clearEvents();
|
||||
|
||||
var prevRowCnt = tbody.find('tr').length;
|
||||
if (rowCnt < prevRowCnt) {
|
||||
tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows
|
||||
}
|
||||
else if (rowCnt > prevRowCnt) { // needs to create new rows...
|
||||
s = '';
|
||||
for (i=prevRowCnt; i<rowCnt; i++) {
|
||||
s += "<tr class='fc-week" + i + "'>";
|
||||
for (j=0; j<colCnt; j++) {
|
||||
s += "<td class='fc-" +
|
||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||
tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
|
||||
(j==dit ? ' fc-leftmost' : '') + "'>" +
|
||||
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
|
||||
"<div class='fc-day-content'><div style='position:relative'> </div></div>" +
|
||||
"</td>";
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
}
|
||||
s += "</tr>";
|
||||
}
|
||||
tbody.append(s);
|
||||
}
|
||||
dayBind(tbody.find('td.fc-new').removeClass('fc-new'));
|
||||
|
||||
// re-label and re-class existing cells
|
||||
d = cloneDate(view.visStart);
|
||||
tbody.find('td').each(function() {
|
||||
var td = $(this);
|
||||
if (rowCnt > 1) {
|
||||
if (d.getMonth() == month) {
|
||||
td.removeClass('fc-other-month');
|
||||
}else{
|
||||
td.addClass('fc-other-month');
|
||||
}
|
||||
}
|
||||
if (+d == +today) {
|
||||
td.removeClass('fc-not-today')
|
||||
.addClass('fc-today')
|
||||
.addClass(tm + '-state-highlight');
|
||||
}else{
|
||||
td.addClass('fc-not-today')
|
||||
.removeClass('fc-today')
|
||||
.removeClass(tm + '-state-highlight');
|
||||
}
|
||||
td.find('div.fc-day-number').text(d.getDate());
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
if (rowCnt == 1) { // more changes likely (week or day view)
|
||||
|
||||
// redo column header text and class
|
||||
d = cloneDate(view.visStart);
|
||||
thead.find('th').each(function() {
|
||||
$(this).text(formatDate(d, colFormat, options));
|
||||
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
// redo cell day-of-weeks
|
||||
d = cloneDate(view.visStart);
|
||||
tbody.find('td').each(function() {
|
||||
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||
addDays(d, 1);
|
||||
if (nwe) {
|
||||
skipWeekend(d);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setHeight(height) {
|
||||
viewHeight = height;
|
||||
var leftTDs = tbody.find('tr td:first-child'),
|
||||
tbodyHeight = viewHeight - thead.height(),
|
||||
rowHeight1, rowHeight2;
|
||||
if (options.weekMode == 'variable') {
|
||||
rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6));
|
||||
}else{
|
||||
rowHeight1 = Math.floor(tbodyHeight / rowCnt);
|
||||
rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
|
||||
}
|
||||
if (tdHeightBug === undefined) {
|
||||
// bug in firefox where cell height includes padding
|
||||
var tr = tbody.find('tr:first'),
|
||||
td = tr.find('td:first');
|
||||
td.height(rowHeight1);
|
||||
tdHeightBug = rowHeight1 != td.height();
|
||||
}
|
||||
if (tdHeightBug) {
|
||||
leftTDs.slice(0, -1).height(rowHeight1);
|
||||
leftTDs.slice(-1).height(rowHeight2);
|
||||
}else{
|
||||
setOuterHeight(leftTDs.slice(0, -1), rowHeight1);
|
||||
setOuterHeight(leftTDs.slice(-1), rowHeight2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setWidth(width) {
|
||||
viewWidth = width;
|
||||
dayContentPositions.clear();
|
||||
setOuterWidth(
|
||||
thead.find('th').slice(0, -1),
|
||||
colWidth = Math.floor(viewWidth / colCnt)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function renderEvents(events) {
|
||||
view.reportEvents(cachedEvents = events);
|
||||
renderSegs(compileSegs(events));
|
||||
}
|
||||
|
||||
|
||||
function rerenderEvents(modifiedEventId) {
|
||||
clearEvents();
|
||||
renderSegs(compileSegs(cachedEvents), modifiedEventId);
|
||||
}
|
||||
|
||||
|
||||
function clearEvents() {
|
||||
view._clearEvents(); // only clears the hashes
|
||||
segmentContainer.empty();
|
||||
}
|
||||
|
||||
|
||||
function compileSegs(events) {
|
||||
var d1 = cloneDate(view.visStart),
|
||||
d2 = addDays(cloneDate(d1), colCnt),
|
||||
visEventsEnds = $.map(events, exclEndDay),
|
||||
i, row,
|
||||
j, level,
|
||||
k, seg,
|
||||
segs=[];
|
||||
for (i=0; i<rowCnt; i++) {
|
||||
row = stackSegs(view.sliceSegs(events, visEventsEnds, d1, d2));
|
||||
for (j=0; j<row.length; j++) {
|
||||
level = row[j];
|
||||
for (k=0; k<level.length; k++) {
|
||||
seg = level[k];
|
||||
seg.row = i;
|
||||
seg.level = j;
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
addDays(d1, 7);
|
||||
addDays(d2, 7);
|
||||
}
|
||||
return segs;
|
||||
}
|
||||
|
||||
|
||||
function renderSegs(segs, modifiedEventId) {
|
||||
_renderDaySegs(
|
||||
segs,
|
||||
rowCnt,
|
||||
view,
|
||||
0,
|
||||
viewWidth,
|
||||
function(i) { return tbody.find('tr:eq('+i+')') },
|
||||
dayContentPositions.left,
|
||||
dayContentPositions.right,
|
||||
segmentContainer,
|
||||
bindSegHandlers,
|
||||
modifiedEventId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function bindSegHandlers(event, eventElement, seg) {
|
||||
view.eventElementHandlers(event, eventElement);
|
||||
if (event.editable || event.editable === undefined && options.editable) {
|
||||
draggableEvent(event, eventElement);
|
||||
if (seg.isEnd) {
|
||||
view.resizableDayEvent(event, eventElement, colWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Event Dragging
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function draggableEvent(event, eventElement) {
|
||||
if (!options.disableDragging && eventElement.draggable) {
|
||||
var dayDelta;
|
||||
eventElement.draggable({
|
||||
zIndex: 9,
|
||||
delay: 50,
|
||||
opacity: view.option('dragOpacity'),
|
||||
revertDuration: options.dragRevertDuration,
|
||||
start: function(ev, ui) {
|
||||
view.trigger('eventDragStart', eventElement, event, ev, ui);
|
||||
view.hideEvents(event, eventElement);
|
||||
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
||||
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
||||
clearOverlay();
|
||||
if (cell) {
|
||||
dayDelta = rowDelta*7 + colDelta*dis;
|
||||
renderDayOverlay(
|
||||
addDays(cloneDate(event.start), dayDelta),
|
||||
addDays(exclEndDay(event), dayDelta)
|
||||
);
|
||||
}else{
|
||||
dayDelta = 0;
|
||||
}
|
||||
}, ev, 'drag');
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
hoverListener.stop();
|
||||
clearOverlay();
|
||||
view.trigger('eventDragStop', eventElement, event, ev, ui);
|
||||
if (dayDelta) {
|
||||
eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
||||
view.eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
|
||||
}else{
|
||||
if ($.browser.msie) {
|
||||
eventElement.css('filter', ''); // clear IE opacity side-effects
|
||||
}
|
||||
view.showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Day clicking and binding
|
||||
---------------------------------------------------------*/
|
||||
|
||||
function dayBind(days) {
|
||||
days.click(dayClick)
|
||||
.mousedown(selectionMousedown);
|
||||
}
|
||||
|
||||
function dayClick(ev) {
|
||||
if (!view.option('selectable')) { // SelectionManager will worry about dayClick
|
||||
var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]),
|
||||
date = addDays(
|
||||
cloneDate(view.visStart),
|
||||
Math.floor(n/colCnt) * 7 + n % colCnt
|
||||
);
|
||||
// TODO: what about weekends in middle of week?
|
||||
view.trigger('dayClick', this, date, true, ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Coordinate Utilities
|
||||
--------------------------------------------------------*/
|
||||
|
||||
var coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
||||
var e, n, p;
|
||||
var tds = tbody.find('tr:first td');
|
||||
if (rtl) {
|
||||
tds = $(tds.get().reverse());
|
||||
}
|
||||
tds.each(function(i, _e) {
|
||||
e = $(_e);
|
||||
n = e.offset().left;
|
||||
if (i) {
|
||||
p[1] = n;
|
||||
}
|
||||
p = [n];
|
||||
cols[i] = p;
|
||||
});
|
||||
p[1] = n + e.outerWidth();
|
||||
tbody.find('tr').each(function(i, _e) {
|
||||
e = $(_e);
|
||||
n = e.offset().top;
|
||||
if (i) {
|
||||
p[1] = n;
|
||||
}
|
||||
p = [n];
|
||||
rows[i] = p;
|
||||
});
|
||||
p[1] = n + e.outerHeight();
|
||||
});
|
||||
|
||||
var hoverListener = new HoverListener(coordinateGrid);
|
||||
|
||||
|
||||
|
||||
/* Selecting
|
||||
--------------------------------------------------------*/
|
||||
|
||||
var selected = false;
|
||||
var selectionMousedown = selection_dayMousedown(
|
||||
view, hoverListener, cellDate, function(){return true}, renderDayOverlay, clearOverlay, reportSelection, unselect
|
||||
);
|
||||
|
||||
view.select = function(startDate, endDate, allDay) {
|
||||
coordinateGrid.build();
|
||||
unselect();
|
||||
if (!endDate) {
|
||||
endDate = cloneDate(startDate);
|
||||
}
|
||||
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1));
|
||||
reportSelection(startDate, endDate, allDay);
|
||||
};
|
||||
|
||||
function reportSelection(startDate, endDate, allDay, ev) {
|
||||
selected = true;
|
||||
view.trigger('select', view, startDate, endDate, allDay, ev);
|
||||
}
|
||||
|
||||
function unselect(ev) {
|
||||
if (selected) {
|
||||
clearOverlay();
|
||||
selected = false;
|
||||
view.trigger('unselect', view, ev);
|
||||
}
|
||||
}
|
||||
view.unselect = unselect;
|
||||
|
||||
selection_unselectAuto(view, unselect);
|
||||
|
||||
|
||||
|
||||
/* External dragging
|
||||
------------------------------------------------------*/
|
||||
|
||||
view.dragStart = function(_dragElement, ev, ui) {
|
||||
hoverListener.start(function(cell) {
|
||||
clearOverlay();
|
||||
if (cell) {
|
||||
_renderDayOverlay(cell.row, cell.col, cell.row, cell.col);
|
||||
}
|
||||
}, ev);
|
||||
};
|
||||
|
||||
view.dragStop = function(_dragElement, ev, ui) {
|
||||
var cell = hoverListener.stop();
|
||||
clearOverlay();
|
||||
if (cell) {
|
||||
var d = cellDate(cell);
|
||||
view.trigger('drop', _dragElement, d, true, ev, ui);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Semi-transparent Overlay Helpers
|
||||
------------------------------------------------------*/
|
||||
|
||||
function renderDayOverlay(overlayStart, overlayEnd) { // overlayEnd is exclusive
|
||||
var rowStart = cloneDate(view.visStart);
|
||||
var rowEnd = addDays(cloneDate(rowStart), colCnt);
|
||||
for (var i=0; i<rowCnt; i++) {
|
||||
var stretchStart = new Date(Math.max(rowStart, overlayStart));
|
||||
var stretchEnd = new Date(Math.min(rowEnd, overlayEnd));
|
||||
if (stretchStart < stretchEnd) {
|
||||
var colStart, colEnd;
|
||||
if (rtl) {
|
||||
colStart = dayDiff(stretchEnd, rowStart)*dis+dit+1;
|
||||
colEnd = dayDiff(stretchStart, rowStart)*dis+dit+1;
|
||||
}else{
|
||||
colStart = dayDiff(stretchStart, rowStart);
|
||||
colEnd = dayDiff(stretchEnd, rowStart);
|
||||
}
|
||||
dayBind(
|
||||
_renderDayOverlay(i, colStart, i, colEnd-1)
|
||||
);
|
||||
}
|
||||
addDays(rowStart, 7);
|
||||
addDays(rowEnd, 7);
|
||||
}
|
||||
}
|
||||
|
||||
function _renderDayOverlay(row0, col0, row1, col1) { // row1,col1 is inclusive
|
||||
var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
|
||||
return view.renderOverlay(rect, element);
|
||||
}
|
||||
|
||||
function clearOverlay() {
|
||||
view.clearOverlays();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Date Utils
|
||||
---------------------------------------------------*/
|
||||
|
||||
|
||||
function cellDate(cell) {
|
||||
return addDays(cloneDate(view.visStart), cell.row*7 + cell.col*dis+dit);
|
||||
// TODO: what about weekends in middle of week?
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function _renderDaySegs(segs, rowCnt, view, minLeft, maxLeft, getRow, dayContentLeft, dayContentRight, segmentContainer, bindSegHandlers, modifiedEventId) {
|
||||
|
||||
var options=view.options,
|
||||
rtl=options.isRTL,
|
||||
i, segCnt=segs.length, seg,
|
||||
event,
|
||||
className,
|
||||
left, right,
|
||||
html='',
|
||||
eventElements,
|
||||
eventElement,
|
||||
triggerRes,
|
||||
hsideCache={},
|
||||
vmarginCache={},
|
||||
key, val,
|
||||
rowI, top, levelI, levelHeight,
|
||||
rowDivs=[],
|
||||
rowDivTops=[];
|
||||
|
||||
// calculate desired position/dimensions, create html
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
event = seg.event;
|
||||
className = 'fc-event fc-event-hori ';
|
||||
if (rtl) {
|
||||
if (seg.isStart) {
|
||||
className += 'fc-corner-right ';
|
||||
}
|
||||
if (seg.isEnd) {
|
||||
className += 'fc-corner-left ';
|
||||
}
|
||||
left = seg.isEnd ? dayContentLeft(seg.end.getDay()-1) : minLeft;
|
||||
right = seg.isStart ? dayContentRight(seg.start.getDay()) : maxLeft;
|
||||
}else{
|
||||
if (seg.isStart) {
|
||||
className += 'fc-corner-left ';
|
||||
}
|
||||
if (seg.isEnd) {
|
||||
className += 'fc-corner-right ';
|
||||
}
|
||||
left = seg.isStart ? dayContentLeft(seg.start.getDay()) : minLeft;
|
||||
right = seg.isEnd ? dayContentRight(seg.end.getDay()-1) : maxLeft;
|
||||
}
|
||||
html +=
|
||||
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;left:"+left+"px'>" +
|
||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||
(!event.allDay && seg.isStart ?
|
||||
"<span class='fc-event-time'>" +
|
||||
htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'), options)) +
|
||||
"</span>"
|
||||
:'') +
|
||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||
"</a>" +
|
||||
((event.editable || event.editable === undefined && options.editable) && !options.disableResizing && $.fn.resizable ?
|
||||
"<div class='ui-resizable-handle ui-resizable-" + (rtl ? 'w' : 'e') + "'></div>"
|
||||
: '') +
|
||||
"</div>";
|
||||
seg.left = left;
|
||||
seg.outerWidth = right - left;
|
||||
}
|
||||
segmentContainer[0].innerHTML = html; // faster than html()
|
||||
eventElements = segmentContainer.children();
|
||||
|
||||
// retrieve elements, run through eventRender callback, bind handlers
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
eventElement = $(eventElements[i]); // faster than eq()
|
||||
event = seg.event;
|
||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||
if (triggerRes === false) {
|
||||
eventElement.remove();
|
||||
}else{
|
||||
if (triggerRes && triggerRes !== true) {
|
||||
eventElement.remove();
|
||||
eventElement = $(triggerRes)
|
||||
.css({
|
||||
position: 'absolute',
|
||||
left: seg.left
|
||||
})
|
||||
.appendTo(segmentContainer);
|
||||
}
|
||||
seg.element = eventElement;
|
||||
if (event._id === modifiedEventId) {
|
||||
bindSegHandlers(event, eventElement, seg);
|
||||
}else{
|
||||
eventElement[0]._fci = i; // for lazySegBind
|
||||
}
|
||||
view.reportEventElement(event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
lazySegBind(segmentContainer, segs, bindSegHandlers);
|
||||
|
||||
// record event horizontal sides
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
val = hsideCache[key = seg.key = cssKey(eventElement[0])];
|
||||
seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
||||
}
|
||||
}
|
||||
|
||||
// set event widths
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
// record event heights
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
val = vmarginCache[key = seg.key];
|
||||
seg.outerHeight = eventElement[0].offsetHeight + (
|
||||
val === undefined ? (vmarginCache[key] = vmargins(eventElement[0])) : val
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// set row heights, calculate event tops (in relation to row top)
|
||||
for (i=0, rowI=0; rowI<rowCnt; rowI++) {
|
||||
top = levelI = levelHeight = 0;
|
||||
while (i<segCnt && (seg = segs[i]).row == rowI) {
|
||||
if (seg.level != levelI) {
|
||||
top += levelHeight;
|
||||
levelHeight = 0;
|
||||
levelI++;
|
||||
}
|
||||
levelHeight = Math.max(levelHeight, seg.outerHeight||0);
|
||||
seg.top = top;
|
||||
i++;
|
||||
}
|
||||
rowDivs[rowI] = getRow(rowI).find('td:first div.fc-day-content > div') // optimal selector?
|
||||
.height(top + levelHeight);
|
||||
}
|
||||
|
||||
// calculate row tops
|
||||
for (rowI=0; rowI<rowCnt; rowI++) {
|
||||
rowDivTops[rowI] = rowDivs[rowI][0].offsetTop;
|
||||
}
|
||||
|
||||
// set event tops
|
||||
for (i=0; i<segCnt; i++) {
|
||||
seg = segs[i];
|
||||
if (eventElement = seg.element) {
|
||||
eventElement[0].style.top = rowDivTops[seg.row] + seg.top + 'px';
|
||||
event = seg.event;
|
||||
view.trigger('eventAfterRender', event, event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
19
src/intro.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @preserve
|
||||
* FullCalendar v@VERSION
|
||||
* http://arshaw.com/fullcalendar/
|
||||
*
|
||||
* Use fullcalendar.css for basic styling.
|
||||
* For event drag & drop, requires jQuery UI draggable.
|
||||
* For event resizing, requires jQuery UI resizable.
|
||||
*
|
||||
* Copyright (c) 2010 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: @DATE
|
||||
*
|
||||
*/
|
||||
|
||||
(function($, undefined) {
|
||||
|
|
@ -10,6 +10,9 @@
|
|||
*/
|
||||
|
||||
|
||||
/* TODO: make font sizes look the same in all doctypes */
|
||||
|
||||
|
||||
.fc,
|
||||
.fc .fc-header,
|
||||
.fc .fc-content {
|
||||
|
@ -232,129 +235,3 @@ table.fc-header {
|
|||
|
||||
|
||||
|
||||
/* Global Event Styles
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event,
|
||||
.fc-agenda .fc-event-time,
|
||||
.fc-event a {
|
||||
border-style: solid;
|
||||
border-color: #36c; /* default BORDER color (probably the same as background-color) */
|
||||
background-color: #36c; /* default BACKGROUND color */
|
||||
color: #fff; /* default TEXT color */
|
||||
}
|
||||
|
||||
/* Use the 'className' CalEvent property and the following
|
||||
* example CSS to change event color on a per-event basis:
|
||||
*
|
||||
* .myclass,
|
||||
* .fc-agenda .myclass .fc-event-time,
|
||||
* .myclass a {
|
||||
* background-color: black;
|
||||
* border-color: black;
|
||||
* color: red;
|
||||
* }
|
||||
*/
|
||||
|
||||
.fc-event {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.fc-event a {
|
||||
overflow: hidden;
|
||||
font-size: .85em;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-event-editable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-event-time,
|
||||
.fc-event-title {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
/* for fake rounded corners */
|
||||
|
||||
.fc-event a {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* right-to-left */
|
||||
|
||||
.fc-rtl .fc-event a {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* resizable */
|
||||
|
||||
.fc .ui-resizable-handle {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
border: 0 !important; /* important overrides pre jquery ui 1.7 styles */
|
||||
background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Horizontal Events
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event-hori {
|
||||
border-width: 1px 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.fc-event-hori a {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* for fake rounded corners */
|
||||
|
||||
.fc-content .fc-corner-left {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-left a {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-right {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.fc-content .fc-corner-right a {
|
||||
margin-right: -1px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
/* resizable */
|
||||
|
||||
.fc-event-hori .ui-resizable-e {
|
||||
top: 0 !important; /* importants override pre jquery ui 1.7 styles */
|
||||
right: -3px !important;
|
||||
width: 7px !important;
|
||||
height: 100% !important;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.fc-event-hori .ui-resizable-w {
|
||||
top: 0 !important;
|
||||
left: -3px !important;
|
||||
width: 7px !important;
|
||||
height: 100% !important;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.fc-event-hori .ui-resizable-handle {
|
||||
_padding-bottom: 14px; /* IE6 had 0 height */
|
||||
}
|
||||
|
||||
|
890
src/main.js
|
@ -1,126 +1,25 @@
|
|||
|
||||
|
||||
var fc = $.fullCalendar = {};
|
||||
var views = fc.views = {};
|
||||
var fcViews = fc.views = {};
|
||||
|
||||
|
||||
/* Defaults
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var defaults = {
|
||||
|
||||
// display
|
||||
defaultView: 'month',
|
||||
aspectRatio: 1.35,
|
||||
header: {
|
||||
left: 'title',
|
||||
center: '',
|
||||
right: 'today prev,next'
|
||||
},
|
||||
weekends: true,
|
||||
|
||||
// editing
|
||||
//editable: false,
|
||||
//disableDragging: false,
|
||||
//disableResizing: false,
|
||||
|
||||
allDayDefault: true,
|
||||
|
||||
// event ajax
|
||||
lazyFetching: true,
|
||||
startParam: 'start',
|
||||
endParam: 'end',
|
||||
|
||||
// time formats
|
||||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
|
||||
day: 'dddd, MMM d, yyyy'
|
||||
},
|
||||
columnFormat: {
|
||||
month: 'ddd',
|
||||
week: 'ddd M/d',
|
||||
day: 'dddd M/d'
|
||||
},
|
||||
timeFormat: { // for event elements
|
||||
'': 'h(:mm)t' // default
|
||||
},
|
||||
|
||||
// locale
|
||||
isRTL: false,
|
||||
firstDay: 0,
|
||||
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
||||
monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
||||
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
||||
dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
||||
buttonText: {
|
||||
prev: ' ◄ ',
|
||||
next: ' ► ',
|
||||
prevYear: ' << ',
|
||||
nextYear: ' >> ',
|
||||
today: 'today',
|
||||
month: 'month',
|
||||
week: 'week',
|
||||
day: 'day'
|
||||
},
|
||||
|
||||
// jquery-ui theming
|
||||
theme: false,
|
||||
buttonIcons: {
|
||||
prev: 'circle-triangle-w',
|
||||
next: 'circle-triangle-e'
|
||||
},
|
||||
|
||||
//selectable: false,
|
||||
unselectAuto: true,
|
||||
|
||||
dropAccept: '*'
|
||||
|
||||
};
|
||||
|
||||
// right-to-left defaults
|
||||
var rtlDefaults = {
|
||||
header: {
|
||||
left: 'next,prev today',
|
||||
center: '',
|
||||
right: 'title'
|
||||
},
|
||||
buttonText: {
|
||||
prev: ' ► ',
|
||||
next: ' ◄ ',
|
||||
prevYear: ' >> ',
|
||||
nextYear: ' << '
|
||||
},
|
||||
buttonIcons: {
|
||||
prev: 'circle-triangle-e',
|
||||
next: 'circle-triangle-w'
|
||||
}
|
||||
};
|
||||
|
||||
// function for adding/overriding defaults
|
||||
var setDefaults = fc.setDefaults = function(d) {
|
||||
$.extend(true, defaults, d);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* .fullCalendar jQuery function
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
$.fn.fullCalendar = function(options) {
|
||||
|
||||
|
||||
// method calling
|
||||
if (typeof options == 'string') {
|
||||
var args = Array.prototype.slice.call(arguments, 1),
|
||||
res;
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
var res;
|
||||
this.each(function() {
|
||||
var data = $.data(this, 'fullCalendar');
|
||||
if (data) {
|
||||
var meth = data[options];
|
||||
if (meth) {
|
||||
var r = meth.apply(this, args);
|
||||
var calendar = $.data(this, 'fullCalendar');
|
||||
if (calendar && typeof $.isFunction(calendar[options])) {
|
||||
var r = calendar[options].apply(calendar, args);
|
||||
if (res === undefined) {
|
||||
res = r;
|
||||
}
|
||||
if (options == 'destroy') {
|
||||
$.removeData(this, 'fullCalendar');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -130,7 +29,8 @@ $.fn.fullCalendar = function(options) {
|
|||
return this;
|
||||
}
|
||||
|
||||
// pluck the 'events' and 'eventSources' options
|
||||
|
||||
// would like to have this logic in EventManager, but needs to happen before options are extended
|
||||
var eventSources = options.eventSources || [];
|
||||
delete options.eventSources;
|
||||
if (options.events) {
|
||||
|
@ -138,778 +38,30 @@ $.fn.fullCalendar = function(options) {
|
|||
delete options.events;
|
||||
}
|
||||
|
||||
// first event source reserved for 'sticky' events
|
||||
eventSources.unshift([]);
|
||||
|
||||
// initialize options
|
||||
options = $.extend(true, {},
|
||||
defaults,
|
||||
(options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {},
|
||||
options
|
||||
);
|
||||
var tm = options.theme ? 'ui' : 'fc'; // for making theme classes
|
||||
|
||||
|
||||
this.each(function() {
|
||||
|
||||
|
||||
/* Instance Initialization
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
// element
|
||||
var _element = this,
|
||||
element = $(_element).addClass('fc'),
|
||||
elementOuterWidth,
|
||||
content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>").prependTo(_element),
|
||||
suggestedViewHeight,
|
||||
resizeUID = 0,
|
||||
ignoreWindowResize = 0,
|
||||
date = new Date(),
|
||||
viewName, // the current view name (TODO: look into getting rid of)
|
||||
view, // the current view
|
||||
viewInstances = {},
|
||||
absoluteViewElement;
|
||||
|
||||
|
||||
|
||||
if (options.isRTL) {
|
||||
element.addClass('fc-rtl');
|
||||
}
|
||||
if (options.theme) {
|
||||
element.addClass('ui-widget');
|
||||
}
|
||||
|
||||
setYMD(date, options.year, options.month, options.date);
|
||||
|
||||
|
||||
|
||||
/* View Rendering
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
function changeView(v) {
|
||||
if (v != viewName) {
|
||||
ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
|
||||
|
||||
viewUnselect();
|
||||
|
||||
var oldView = view,
|
||||
newViewElement;
|
||||
|
||||
if (oldView) {
|
||||
if (oldView.eventsChanged) {
|
||||
eventsDirty();
|
||||
oldView.eventDirty = oldView.eventsChanged = false;
|
||||
}
|
||||
if (oldView.beforeHide) {
|
||||
oldView.beforeHide(); // called before changing min-height. if called after, scroll state is reset (in Opera)
|
||||
}
|
||||
setMinHeight(content, content.height());
|
||||
oldView.element.hide();
|
||||
}else{
|
||||
setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated
|
||||
}
|
||||
content.css('overflow', 'hidden');
|
||||
|
||||
if (viewInstances[v]) {
|
||||
(view = viewInstances[v]).element.show();
|
||||
}else{
|
||||
view = viewInstances[v] = fc.views[v](
|
||||
newViewElement = absoluteViewElement =
|
||||
$("<div class='fc-view fc-view-" + v + "' style='position:absolute'/>")
|
||||
.appendTo(content),
|
||||
options,
|
||||
v // the view's name
|
||||
);
|
||||
}
|
||||
|
||||
if (header) {
|
||||
// update 'active' view button
|
||||
header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active');
|
||||
header.find('div.fc-button-' + v).addClass(tm + '-state-active');
|
||||
}
|
||||
|
||||
viewName = v;
|
||||
render(); // after height has been set, will make absoluteViewElement's position=relative, then set to null
|
||||
content.css('overflow', '');
|
||||
if (oldView) {
|
||||
setMinHeight(content, 1);
|
||||
}
|
||||
if (!newViewElement && view.afterShow) {
|
||||
view.afterShow(); // called after setting min-height/overflow, so in final scroll state (for Opera)
|
||||
}
|
||||
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function render(inc) {
|
||||
if (elementVisible()) {
|
||||
ignoreWindowResize++; // because view.renderEvents might temporarily change the height before setSize is reached
|
||||
|
||||
viewUnselect();
|
||||
|
||||
if (suggestedViewHeight === undefined) {
|
||||
calcSize();
|
||||
}
|
||||
|
||||
if (!view.start || inc || date < view.start || date >= view.end) {
|
||||
view.render(date, inc || 0); // responsible for clearing events
|
||||
setSize(true);
|
||||
if (!eventStart || !options.lazyFetching || view.visStart < eventStart || view.visEnd > eventEnd) {
|
||||
fetchAndRenderEvents();
|
||||
}else{
|
||||
view.renderEvents(events); // don't refetch
|
||||
}
|
||||
}
|
||||
else if (view.sizeDirty || view.eventsDirty || !options.lazyFetching) {
|
||||
view.clearEvents();
|
||||
if (view.sizeDirty) {
|
||||
setSize();
|
||||
}
|
||||
if (options.lazyFetching) {
|
||||
view.renderEvents(events); // don't refetch
|
||||
}else{
|
||||
fetchAndRenderEvents();
|
||||
}
|
||||
}
|
||||
elementOuterWidth = element.outerWidth();
|
||||
view.sizeDirty = false;
|
||||
view.eventsDirty = false;
|
||||
|
||||
if (header) {
|
||||
// update title text
|
||||
header.find('h2.fc-header-title').html(view.title);
|
||||
// enable/disable 'today' button
|
||||
var today = new Date();
|
||||
if (today >= view.start && today < view.end) {
|
||||
header.find('div.fc-button-today').addClass(tm + '-state-disabled');
|
||||
}else{
|
||||
header.find('div.fc-button-today').removeClass(tm + '-state-disabled');
|
||||
}
|
||||
}
|
||||
|
||||
ignoreWindowResize--;
|
||||
view.trigger('viewDisplay', _element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function elementVisible() {
|
||||
return _element.offsetWidth !== 0;
|
||||
}
|
||||
|
||||
function bodyVisible() {
|
||||
return $('body')[0].offsetWidth !== 0;
|
||||
}
|
||||
|
||||
function viewUnselect() {
|
||||
if (view) {
|
||||
view.unselect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// called when any event objects have been added/removed/changed, rerenders
|
||||
function eventsChanged() {
|
||||
eventsDirty();
|
||||
if (elementVisible()) {
|
||||
view.clearEvents();
|
||||
view.renderEvents(events);
|
||||
view.eventsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
// marks other views' events as dirty
|
||||
function eventsDirty() {
|
||||
$.each(viewInstances, function() {
|
||||
this.eventsDirty = true;
|
||||
this.each(function(i, _element) {
|
||||
var element = $(_element);
|
||||
var calendar = new Calendar(element, options, eventSources);
|
||||
element.data('fullCalendar', calendar); // TODO: look into memory leak implications
|
||||
calendar.render();
|
||||
});
|
||||
}
|
||||
|
||||
// called when we know the element size has changed
|
||||
function sizeChanged() {
|
||||
sizesDirty();
|
||||
if (elementVisible()) {
|
||||
calcSize();
|
||||
setSize();
|
||||
viewUnselect();
|
||||
view.rerenderEvents();
|
||||
view.sizeDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
// marks other views' sizes as dirty
|
||||
function sizesDirty() {
|
||||
$.each(viewInstances, function() {
|
||||
this.sizeDirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Event Sources and Fetching
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var events = [],
|
||||
eventStart, eventEnd;
|
||||
|
||||
// Fetch from ALL sources. Clear 'events' array and populate
|
||||
function fetchEvents(callback) {
|
||||
events = [];
|
||||
eventStart = cloneDate(view.visStart);
|
||||
eventEnd = cloneDate(view.visEnd);
|
||||
var queued = eventSources.length,
|
||||
sourceDone = function() {
|
||||
if (!--queued) {
|
||||
if (callback) {
|
||||
callback(events);
|
||||
}
|
||||
}
|
||||
}, i=0;
|
||||
for (; i<eventSources.length; i++) {
|
||||
fetchEventSource(eventSources[i], sourceDone);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch from a particular source. Append to the 'events' array
|
||||
function fetchEventSource(src, callback) {
|
||||
var prevViewName = view.name,
|
||||
prevDate = cloneDate(date),
|
||||
reportEvents = function(a) {
|
||||
if (prevViewName == view.name && +prevDate == +date && // protects from fast switching
|
||||
$.inArray(src, eventSources) != -1) { // makes sure source hasn't been removed
|
||||
for (var i=0; i<a.length; i++) {
|
||||
normalizeEvent(a[i], options);
|
||||
a[i].source = src;
|
||||
}
|
||||
events = events.concat(a);
|
||||
if (callback) {
|
||||
callback(a);
|
||||
}
|
||||
}
|
||||
},
|
||||
reportEventsAndPop = function(a) {
|
||||
reportEvents(a);
|
||||
popLoading();
|
||||
};
|
||||
if (typeof src == 'string') {
|
||||
var params = {};
|
||||
params[options.startParam] = Math.round(eventStart.getTime() / 1000);
|
||||
params[options.endParam] = Math.round(eventEnd.getTime() / 1000);
|
||||
if (options.cacheParam) {
|
||||
params[options.cacheParam] = (new Date()).getTime(); // TODO: deprecate cacheParam
|
||||
}
|
||||
pushLoading();
|
||||
$.ajax({
|
||||
url: src,
|
||||
dataType: 'json',
|
||||
data: params,
|
||||
cache: options.cacheParam || false, // don't let jquery prevent caching if cacheParam is being used
|
||||
success: reportEventsAndPop
|
||||
});
|
||||
}
|
||||
else if ($.isFunction(src)) {
|
||||
pushLoading();
|
||||
src(cloneDate(eventStart), cloneDate(eventEnd), reportEventsAndPop);
|
||||
}
|
||||
else {
|
||||
reportEvents(src); // src is an array
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for convenience
|
||||
function fetchAndRenderEvents() {
|
||||
fetchEvents(function(events) {
|
||||
view.renderEvents(events); // maintain `this` in view
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Loading State
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var loadingLevel = 0;
|
||||
|
||||
function pushLoading() {
|
||||
if (!loadingLevel++) {
|
||||
view.trigger('loading', _element, true);
|
||||
}
|
||||
}
|
||||
|
||||
function popLoading() {
|
||||
if (!--loadingLevel) {
|
||||
view.trigger('loading', _element, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Public Methods
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var publicMethods = {
|
||||
|
||||
render: function() {
|
||||
calcSize();
|
||||
sizesDirty();
|
||||
eventsDirty();
|
||||
render();
|
||||
},
|
||||
|
||||
changeView: changeView,
|
||||
|
||||
getView: function() {
|
||||
return view;
|
||||
},
|
||||
|
||||
getDate: function() {
|
||||
return date;
|
||||
},
|
||||
|
||||
option: function(name, value) {
|
||||
if (value === undefined) {
|
||||
return options[name];
|
||||
}
|
||||
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
||||
options[name] = value;
|
||||
sizeChanged();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
$(window).unbind('resize', windowResize);
|
||||
if (header) {
|
||||
header.remove();
|
||||
}
|
||||
content.remove();
|
||||
$.removeData(_element, 'fullCalendar');
|
||||
},
|
||||
|
||||
//
|
||||
// Navigation
|
||||
//
|
||||
|
||||
prev: function() {
|
||||
render(-1);
|
||||
},
|
||||
|
||||
next: function() {
|
||||
render(1);
|
||||
},
|
||||
|
||||
prevYear: function() {
|
||||
addYears(date, -1);
|
||||
render();
|
||||
},
|
||||
|
||||
nextYear: function() {
|
||||
addYears(date, 1);
|
||||
render();
|
||||
},
|
||||
|
||||
today: function() {
|
||||
date = new Date();
|
||||
render();
|
||||
},
|
||||
|
||||
gotoDate: function(year, month, dateNum) {
|
||||
if (typeof year == 'object') {
|
||||
date = cloneDate(year); // provided 1 argument, a Date
|
||||
}else{
|
||||
setYMD(date, year, month, dateNum);
|
||||
}
|
||||
render();
|
||||
},
|
||||
|
||||
incrementDate: function(years, months, days) {
|
||||
if (years !== undefined) {
|
||||
addYears(date, years);
|
||||
}
|
||||
if (months !== undefined) {
|
||||
addMonths(date, months);
|
||||
}
|
||||
if (days !== undefined) {
|
||||
addDays(date, days);
|
||||
}
|
||||
render();
|
||||
},
|
||||
|
||||
//
|
||||
// Event Manipulation
|
||||
//
|
||||
|
||||
updateEvent: function(event) { // update an existing event
|
||||
var i, len = events.length, e,
|
||||
startDelta = event.start - event._start,
|
||||
endDelta = event.end ?
|
||||
(event.end - (event._end || view.defaultEventEnd(event))) // event._end would be null if event.end
|
||||
: 0; // was null and event was just resized
|
||||
for (i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
if (e._id == event._id && e != event) {
|
||||
e.start = new Date(+e.start + startDelta);
|
||||
if (event.end) {
|
||||
if (e.end) {
|
||||
e.end = new Date(+e.end + endDelta);
|
||||
}else{
|
||||
e.end = new Date(+view.defaultEventEnd(e) + endDelta);
|
||||
}
|
||||
}else{
|
||||
e.end = null;
|
||||
}
|
||||
e.title = event.title;
|
||||
e.url = event.url;
|
||||
e.allDay = event.allDay;
|
||||
e.className = event.className;
|
||||
e.editable = event.editable;
|
||||
normalizeEvent(e, options);
|
||||
}
|
||||
}
|
||||
normalizeEvent(event, options);
|
||||
eventsChanged();
|
||||
},
|
||||
|
||||
renderEvent: function(event, stick) { // render a new event
|
||||
normalizeEvent(event, options);
|
||||
if (!event.source) {
|
||||
if (stick) {
|
||||
(event.source = eventSources[0]).push(event);
|
||||
}
|
||||
events.push(event);
|
||||
}
|
||||
eventsChanged();
|
||||
},
|
||||
|
||||
removeEvents: function(filter) {
|
||||
if (!filter) { // remove all
|
||||
events = [];
|
||||
// clear all array sources
|
||||
for (var i=0; i<eventSources.length; i++) {
|
||||
if (typeof eventSources[i] == 'object') {
|
||||
eventSources[i] = [];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (!$.isFunction(filter)) { // an event ID
|
||||
var id = filter + '';
|
||||
filter = function(e) {
|
||||
return e._id == id;
|
||||
};
|
||||
}
|
||||
events = $.grep(events, filter, true);
|
||||
// remove events from array sources
|
||||
for (var i=0; i<eventSources.length; i++) {
|
||||
if (typeof eventSources[i] == 'object') {
|
||||
eventSources[i] = $.grep(eventSources[i], filter, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
eventsChanged();
|
||||
},
|
||||
|
||||
clientEvents: function(filter) {
|
||||
if ($.isFunction(filter)) {
|
||||
return $.grep(events, filter);
|
||||
}
|
||||
else if (filter) { // an event ID
|
||||
filter += '';
|
||||
return $.grep(events, function(e) {
|
||||
return e._id == filter;
|
||||
});
|
||||
}
|
||||
return events; // else, return all
|
||||
},
|
||||
|
||||
rerenderEvents: eventsChanged, // TODO: think of renaming eventsChanged
|
||||
|
||||
//
|
||||
// Event Source
|
||||
//
|
||||
|
||||
addEventSource: function(source) {
|
||||
eventSources.push(source);
|
||||
fetchEventSource(source, eventsChanged);
|
||||
},
|
||||
|
||||
removeEventSource: function(source) {
|
||||
eventSources = $.grep(eventSources, function(src) {
|
||||
return src != source;
|
||||
});
|
||||
// remove all client events from that source
|
||||
events = $.grep(events, function(e) {
|
||||
return e.source != source;
|
||||
});
|
||||
eventsChanged();
|
||||
},
|
||||
|
||||
refetchEvents: function() {
|
||||
fetchEvents(eventsChanged);
|
||||
},
|
||||
|
||||
//
|
||||
// selection
|
||||
//
|
||||
|
||||
select: function(start, end, allDay) {
|
||||
view.select(start, end, allDay===undefined ? true : allDay);
|
||||
},
|
||||
|
||||
unselect: function() {
|
||||
view.unselect();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$.data(this, 'fullCalendar', publicMethods); // TODO: look into memory leak implications
|
||||
|
||||
|
||||
|
||||
/* Header
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var header,
|
||||
sections = options.header;
|
||||
if (sections) {
|
||||
header = $("<table class='fc-header'/>")
|
||||
.append($("<tr/>")
|
||||
.append($("<td class='fc-header-left'/>").append(buildSection(sections.left)))
|
||||
.append($("<td class='fc-header-center'/>").append(buildSection(sections.center)))
|
||||
.append($("<td class='fc-header-right'/>").append(buildSection(sections.right))))
|
||||
.prependTo(element);
|
||||
}
|
||||
function buildSection(buttonStr) {
|
||||
if (buttonStr) {
|
||||
var tr = $("<tr/>");
|
||||
$.each(buttonStr.split(' '), function(i) {
|
||||
if (i > 0) {
|
||||
tr.append("<td><span class='fc-header-space'/></td>");
|
||||
}
|
||||
var prevButton;
|
||||
$.each(this.split(','), function(j, buttonName) {
|
||||
if (buttonName == 'title') {
|
||||
tr.append("<td><h2 class='fc-header-title'> </h2></td>");
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-corner-right');
|
||||
}
|
||||
prevButton = null;
|
||||
}else{
|
||||
var buttonClick;
|
||||
if (publicMethods[buttonName]) {
|
||||
buttonClick = publicMethods[buttonName];
|
||||
}
|
||||
else if (views[buttonName]) {
|
||||
buttonClick = function() {
|
||||
button.removeClass(tm + '-state-hover');
|
||||
changeView(buttonName);
|
||||
};
|
||||
}
|
||||
if (buttonClick) {
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-no-right');
|
||||
}
|
||||
var button,
|
||||
icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null,
|
||||
text = smartProperty(options.buttonText, buttonName);
|
||||
if (icon) {
|
||||
button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
|
||||
"<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
|
||||
}
|
||||
else if (text) {
|
||||
button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
|
||||
"<a><span>" + text + "</span></a></div>");
|
||||
}
|
||||
if (button) {
|
||||
button
|
||||
.click(function() {
|
||||
if (!button.hasClass(tm + '-state-disabled')) {
|
||||
buttonClick();
|
||||
}
|
||||
})
|
||||
.mousedown(function() {
|
||||
button
|
||||
.not('.' + tm + '-state-active')
|
||||
.not('.' + tm + '-state-disabled')
|
||||
.addClass(tm + '-state-down');
|
||||
})
|
||||
.mouseup(function() {
|
||||
button.removeClass(tm + '-state-down');
|
||||
})
|
||||
.hover(
|
||||
function() {
|
||||
button
|
||||
.not('.' + tm + '-state-active')
|
||||
.not('.' + tm + '-state-disabled')
|
||||
.addClass(tm + '-state-hover');
|
||||
},
|
||||
function() {
|
||||
button
|
||||
.removeClass(tm + '-state-hover')
|
||||
.removeClass(tm + '-state-down');
|
||||
}
|
||||
)
|
||||
.appendTo($("<td/>").appendTo(tr));
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-no-right');
|
||||
}else{
|
||||
button.addClass(tm + '-corner-left');
|
||||
}
|
||||
prevButton = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (prevButton) {
|
||||
prevButton.addClass(tm + '-corner-right');
|
||||
}
|
||||
});
|
||||
return $("<table/>").append(tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Resizing
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function calcSize() {
|
||||
if (options.contentHeight) {
|
||||
suggestedViewHeight = options.contentHeight;
|
||||
}
|
||||
else if (options.height) {
|
||||
suggestedViewHeight = options.height - (header ? header.height() : 0) - vsides(content[0]);
|
||||
}
|
||||
else {
|
||||
suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setSize(dateChanged) {
|
||||
ignoreWindowResize++;
|
||||
view.setHeight(suggestedViewHeight, dateChanged);
|
||||
if (absoluteViewElement) {
|
||||
absoluteViewElement.css('position', 'relative');
|
||||
absoluteViewElement = null;
|
||||
}
|
||||
view.setWidth(content.width(), dateChanged);
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
|
||||
|
||||
function windowResize() {
|
||||
if (!ignoreWindowResize) {
|
||||
if (view.start) { // view has already been rendered
|
||||
var uid = ++resizeUID;
|
||||
setTimeout(function() { // add a delay
|
||||
if (uid == resizeUID && !ignoreWindowResize && elementVisible()) {
|
||||
if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {
|
||||
ignoreWindowResize++; // in case the windowResize callback changes the height
|
||||
sizeChanged();
|
||||
view.trigger('windowResize', _element);
|
||||
ignoreWindowResize--;
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
}else{
|
||||
// calendar must have been initialized in a 0x0 iframe that has just been resized
|
||||
lateRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
$(window).resize(windowResize);
|
||||
|
||||
|
||||
|
||||
/* External event dropping
|
||||
--------------------------------------------------------*/
|
||||
|
||||
if (options.droppable) {
|
||||
var _dragElement;
|
||||
$(document)
|
||||
.bind('dragstart', function(ev, ui) {
|
||||
var _e = ev.target;
|
||||
var e = $(_e);
|
||||
if (!e.parents('.fc').length) { // not already inside a calendar
|
||||
var accept = options.dropAccept;
|
||||
if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) {
|
||||
_dragElement = _e;
|
||||
view.dragStart(_dragElement, ev, ui);
|
||||
}
|
||||
}
|
||||
})
|
||||
.bind('dragstop', function(ev, ui) {
|
||||
if (_dragElement) {
|
||||
view.dragStop(_dragElement, ev, ui);
|
||||
_dragElement = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// let's begin...
|
||||
changeView(options.defaultView);
|
||||
|
||||
|
||||
// needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize
|
||||
if (!bodyVisible()) {
|
||||
lateRender();
|
||||
}
|
||||
|
||||
|
||||
// called when we know the calendar couldn't be rendered when it was initialized,
|
||||
// but we think it's ready now
|
||||
function lateRender() {
|
||||
setTimeout(function() { // IE7 needs this so dimensions are calculated correctly
|
||||
if (!view.start && bodyVisible()) { // !view.start makes sure this never happens more than once
|
||||
render();
|
||||
}
|
||||
},0);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// function for adding/overriding defaults
|
||||
function setDefaults(d) {
|
||||
$.extend(true, defaults, d);
|
||||
}
|
||||
|
||||
/* Important Event Utilities
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var fakeID = 0;
|
||||
|
||||
function normalizeEvent(event, options) {
|
||||
event._id = event._id || (event.id === undefined ? '_fc' + fakeID++ : event.id + '');
|
||||
if (event.date) {
|
||||
if (!event.start) {
|
||||
event.start = event.date;
|
||||
}
|
||||
delete event.date;
|
||||
}
|
||||
event._start = cloneDate(event.start = parseDate(event.start));
|
||||
event.end = parseDate(event.end);
|
||||
if (event.end && event.end <= event.start) {
|
||||
event.end = null;
|
||||
}
|
||||
event._end = event.end ? cloneDate(event.end) : null;
|
||||
if (event.allDay === undefined) {
|
||||
event.allDay = options.allDayDefault;
|
||||
}
|
||||
if (event.className) {
|
||||
if (typeof event.className == 'string') {
|
||||
event.className = event.className.split(/\s+/);
|
||||
}
|
||||
}else{
|
||||
event.className = [];
|
||||
}
|
||||
}
|
||||
// TODO: if there is no start date, return false to indicate an invalid event
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
* @preserve
|
||||
* FullCalendar v@VERSION
|
||||
* http://arshaw.com/fullcalendar/
|
||||
*
|
||||
* Use fullcalendar.css for basic styling.
|
||||
* For event drag & drop, required jQuery UI draggable.
|
||||
* For event resizing, requires jQuery UI resizable.
|
||||
*
|
||||
* Copyright (c) 2009 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Date: @DATE
|
||||
*
|
||||
*/
|
||||
|
||||
(function($, undefined) {
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
|
||||
function selection_dayMousedown(view, hoverListener, cellDate, cellIsAllDay, renderSelection, clearSelection, reportSelection, unselect) {
|
||||
return function(ev) {
|
||||
if (view.option('selectable')) {
|
||||
unselect(ev);
|
||||
var _mousedownElement = this;
|
||||
var dates;
|
||||
hoverListener.start(function(cell, origCell) {
|
||||
clearSelection();
|
||||
if (cell && cellIsAllDay(cell)) {
|
||||
dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);
|
||||
renderSelection(dates[0], addDays(cloneDate(dates[1]), 1), true);
|
||||
}else{
|
||||
dates = null;
|
||||
}
|
||||
}, ev);
|
||||
$(document).one('mouseup', function(ev) {
|
||||
hoverListener.stop();
|
||||
if (dates) {
|
||||
if (+dates[0] == +dates[1]) {
|
||||
view.trigger('dayClick', _mousedownElement, dates[0], true, ev);
|
||||
// BUG: _mousedownElement will sometimes be the overlay
|
||||
}
|
||||
reportSelection(dates[0], dates[1], true, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function selection_unselectAuto(view, unselect) {
|
||||
if (view.option('selectable') && view.option('unselectAuto')) {
|
||||
$(document).mousedown(function(ev) {
|
||||
var ignore = view.option('unselectCancel');
|
||||
if (ignore) {
|
||||
if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match
|
||||
return;
|
||||
}
|
||||
}
|
||||
unselect(ev);
|
||||
});
|
||||
}
|
||||
}
|
375
src/view.js
|
@ -1,375 +0,0 @@
|
|||
|
||||
/* Methods & Utilities for All Views
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
var viewMethods = {
|
||||
|
||||
/*
|
||||
* Objects inheriting these methods must implement the following properties/methods:
|
||||
* - title
|
||||
* - start
|
||||
* - end
|
||||
* - visStart
|
||||
* - visEnd
|
||||
* - defaultEventEnd(event)
|
||||
* - render(events)
|
||||
* - rerenderEvents()
|
||||
*
|
||||
*
|
||||
* z-index reservations:
|
||||
* 3 - day-overlay
|
||||
* 8 - events
|
||||
* 9 - dragging/resizing events
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
init: function(element, options) {
|
||||
this.element = element;
|
||||
this.options = options;
|
||||
this.eventsByID = {};
|
||||
this.eventElements = [];
|
||||
this.eventElementsByID = {};
|
||||
this.usedOverlays = [];
|
||||
this.unusedOverlays = [];
|
||||
},
|
||||
|
||||
|
||||
|
||||
// triggers an event handler, always append view as last arg
|
||||
|
||||
trigger: function(name, thisObj) {
|
||||
if (this.options[name]) {
|
||||
return this.options[name].apply(thisObj || this, Array.prototype.slice.call(arguments, 2).concat([this]));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// returns a Date object for an event's end
|
||||
|
||||
eventEnd: function(event) {
|
||||
return event.end ? cloneDate(event.end) : this.defaultEventEnd(event); // TODO: make sure always using copies
|
||||
},
|
||||
|
||||
|
||||
|
||||
// report when view receives new events
|
||||
|
||||
reportEvents: function(events) { // events are already normalized at this point
|
||||
var i, len=events.length, event,
|
||||
eventsByID = this.eventsByID = {};
|
||||
for (i=0; i<len; i++) {
|
||||
event = events[i];
|
||||
if (eventsByID[event._id]) {
|
||||
eventsByID[event._id].push(event);
|
||||
}else{
|
||||
eventsByID[event._id] = [event];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// report when view creates an element for an event
|
||||
|
||||
reportEventElement: function(event, element) {
|
||||
this.eventElements.push(element);
|
||||
var eventElementsByID = this.eventElementsByID;
|
||||
if (eventElementsByID[event._id]) {
|
||||
eventElementsByID[event._id].push(element);
|
||||
}else{
|
||||
eventElementsByID[event._id] = [element];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// event element manipulation
|
||||
|
||||
_clearEvents: function() { // only resets hashes
|
||||
this.eventElements = [];
|
||||
this.eventElementsByID = {};
|
||||
},
|
||||
|
||||
showEvents: function(event, exceptElement) {
|
||||
this._eee(event, exceptElement, 'show');
|
||||
},
|
||||
|
||||
hideEvents: function(event, exceptElement) {
|
||||
this._eee(event, exceptElement, 'hide');
|
||||
},
|
||||
|
||||
_eee: function(event, exceptElement, funcName) { // event-element-each
|
||||
var elements = this.eventElementsByID[event._id],
|
||||
i, len = elements.length;
|
||||
for (i=0; i<len; i++) {
|
||||
if (elements[i][0] != exceptElement[0]) { // AHAHAHAHAHAHAHAH
|
||||
elements[i][funcName]();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// event modification reporting
|
||||
|
||||
eventDrop: function(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
|
||||
var view = this,
|
||||
oldAllDay = event.allDay,
|
||||
eventId = event._id;
|
||||
view.moveEvents(view.eventsByID[eventId], dayDelta, minuteDelta, allDay);
|
||||
view.trigger('eventDrop', e, event, dayDelta, minuteDelta, allDay, function() { // TODO: change docs
|
||||
// TODO: investigate cases where this inverse technique might not work
|
||||
view.moveEvents(view.eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
|
||||
view.rerenderEvents();
|
||||
}, ev, ui);
|
||||
view.eventsChanged = true;
|
||||
view.rerenderEvents(eventId);
|
||||
},
|
||||
|
||||
eventResize: function(e, event, dayDelta, minuteDelta, ev, ui) {
|
||||
var view = this,
|
||||
eventId = event._id;
|
||||
view.elongateEvents(view.eventsByID[eventId], dayDelta, minuteDelta);
|
||||
view.trigger('eventResize', e, event, dayDelta, minuteDelta, function() {
|
||||
// TODO: investigate cases where this inverse technique might not work
|
||||
view.elongateEvents(view.eventsByID[eventId], -dayDelta, -minuteDelta);
|
||||
view.rerenderEvents();
|
||||
}, ev, ui);
|
||||
view.eventsChanged = true;
|
||||
view.rerenderEvents(eventId);
|
||||
},
|
||||
|
||||
|
||||
|
||||
// event modification
|
||||
|
||||
moveEvents: function(events, dayDelta, minuteDelta, allDay) {
|
||||
minuteDelta = minuteDelta || 0;
|
||||
for (var e, len=events.length, i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
if (allDay !== undefined) {
|
||||
e.allDay = allDay;
|
||||
}
|
||||
addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
|
||||
if (e.end) {
|
||||
e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
|
||||
}
|
||||
normalizeEvent(e, this.options);
|
||||
}
|
||||
},
|
||||
|
||||
elongateEvents: function(events, dayDelta, minuteDelta) {
|
||||
minuteDelta = minuteDelta || 0;
|
||||
for (var e, len=events.length, i=0; i<len; i++) {
|
||||
e = events[i];
|
||||
e.end = addMinutes(addDays(this.eventEnd(e), dayDelta, true), minuteDelta);
|
||||
normalizeEvent(e, this.options);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// semi-transparent overlay (while dragging or selecting)
|
||||
|
||||
renderOverlay: function(rect, parent) {
|
||||
var e = this.unusedOverlays.shift();
|
||||
if (!e) {
|
||||
e = $("<div class='fc-cell-overlay' style='position:absolute;z-index:3'/>");
|
||||
}
|
||||
if (e[0].parentNode != parent[0]) {
|
||||
e.appendTo(parent);
|
||||
}
|
||||
this.usedOverlays.push(e.css(rect).show());
|
||||
return e;
|
||||
},
|
||||
|
||||
clearOverlays: function() {
|
||||
var e;
|
||||
while (e = this.usedOverlays.shift()) {
|
||||
this.unusedOverlays.push(e.hide().unbind());
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// common horizontal event resizing
|
||||
|
||||
resizableDayEvent: function(event, eventElement, colWidth) {
|
||||
var view = this;
|
||||
if (!view.options.disableResizing && eventElement.resizable) {
|
||||
eventElement.resizable({
|
||||
handles: view.options.isRTL ? {w:'div.ui-resizable-w'} : {e:'div.ui-resizable-e'},
|
||||
grid: colWidth,
|
||||
minWidth: colWidth/2, // need this or else IE throws errors when too small
|
||||
containment: view.element.parent().parent(), // the main element...
|
||||
// ... a fix. wouldn't allow extending to last column in agenda views (jq ui bug?)
|
||||
start: function(ev, ui) {
|
||||
eventElement.css('z-index', 9);
|
||||
view.hideEvents(event, eventElement);
|
||||
view.trigger('eventResizeStart', this, event, ev, ui);
|
||||
},
|
||||
stop: function(ev, ui) {
|
||||
view.trigger('eventResizeStop', this, event, ev, ui);
|
||||
// ui.size.width wasn't working with grid correctly, use .width()
|
||||
var dayDelta = Math.round((eventElement.width() - ui.originalSize.width) / colWidth);
|
||||
if (dayDelta) {
|
||||
view.eventResize(this, event, dayDelta, 0, ev, ui);
|
||||
}else{
|
||||
eventElement.css('z-index', 8);
|
||||
view.showEvents(event, eventElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
// attaches eventClick, eventMouseover, eventMouseout
|
||||
|
||||
eventElementHandlers: function(event, eventElement) {
|
||||
var view = this;
|
||||
eventElement
|
||||
.click(function(ev) {
|
||||
if (!eventElement.hasClass('ui-draggable-dragging') &&
|
||||
!eventElement.hasClass('ui-resizable-resizing')) {
|
||||
return view.trigger('eventClick', this, event, ev);
|
||||
}
|
||||
})
|
||||
.hover(
|
||||
function(ev) {
|
||||
view.trigger('eventMouseover', this, event, ev);
|
||||
},
|
||||
function(ev) {
|
||||
view.trigger('eventMouseout', this, event, ev);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
|
||||
// get a property from the 'options' object, using smart view naming
|
||||
|
||||
option: function(name, viewName) {
|
||||
var v = this.options[name];
|
||||
if (typeof v == 'object') {
|
||||
return smartProperty(v, viewName || this.name);
|
||||
}
|
||||
return v;
|
||||
},
|
||||
|
||||
|
||||
|
||||
// event rendering utilities
|
||||
|
||||
sliceSegs: function(events, visEventEnds, start, end) {
|
||||
var segs = [],
|
||||
i, len=events.length, event,
|
||||
eventStart, eventEnd,
|
||||
segStart, segEnd,
|
||||
isStart, isEnd;
|
||||
for (i=0; i<len; i++) {
|
||||
event = events[i];
|
||||
eventStart = event.start;
|
||||
eventEnd = visEventEnds[i];
|
||||
if (eventEnd > start && eventStart < end) {
|
||||
if (eventStart < start) {
|
||||
segStart = cloneDate(start);
|
||||
isStart = false;
|
||||
}else{
|
||||
segStart = eventStart;
|
||||
isStart = true;
|
||||
}
|
||||
if (eventEnd > end) {
|
||||
segEnd = cloneDate(end);
|
||||
isEnd = false;
|
||||
}else{
|
||||
segEnd = eventEnd;
|
||||
isEnd = true;
|
||||
}
|
||||
segs.push({
|
||||
event: event,
|
||||
start: segStart,
|
||||
end: segEnd,
|
||||
isStart: isStart,
|
||||
isEnd: isEnd,
|
||||
msLength: segEnd - segStart
|
||||
});
|
||||
}
|
||||
}
|
||||
return segs.sort(segCmp);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
function lazySegBind(container, segs, bindHandlers) {
|
||||
container.unbind('mouseover').mouseover(function(ev) {
|
||||
var parent=ev.target, e,
|
||||
i, seg;
|
||||
while (parent != this) {
|
||||
e = parent;
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
if ((i = e._fci) !== undefined) {
|
||||
e._fci = undefined;
|
||||
seg = segs[i];
|
||||
bindHandlers(seg.event, seg.element, seg);
|
||||
$(ev.target).trigger(ev);
|
||||
}
|
||||
ev.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// event rendering calculation utilities
|
||||
|
||||
function stackSegs(segs) {
|
||||
var levels = [],
|
||||
i, len = segs.length, seg,
|
||||
j, collide, k;
|
||||
for (i=0; i<len; i++) {
|
||||
seg = segs[i];
|
||||
j = 0; // the level index where seg should belong
|
||||
while (true) {
|
||||
collide = false;
|
||||
if (levels[j]) {
|
||||
for (k=0; k<levels[j].length; k++) {
|
||||
if (segsCollide(levels[j][k], seg)) {
|
||||
collide = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (collide) {
|
||||
j++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (levels[j]) {
|
||||
levels[j].push(seg);
|
||||
}else{
|
||||
levels[j] = [seg];
|
||||
}
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
|
||||
function segCmp(a, b) {
|
||||
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
||||
}
|
||||
|
||||
function segsCollide(seg1, seg2) {
|
||||
return seg1.end > seg2.start && seg1.start < seg2.end;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript' src='../src/gcal/_loader.js'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#calendar').fullCalendar({
|
||||
//weekends: false,
|
||||
weekends: false,
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="imagetoolbar" content="no" />
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="fancybox/jquery.fancybox-1.2.6.css" media="screen" />
|
||||
<script type="text/javascript" src="fancybox/jquery.fancybox-1.2.6.pack.js"></script>
|
||||
<script type="text/javascript">
|
||||
<link rel='stylesheet' type='text/css' href='lib/fancybox/jquery.fancybox-1.2.6.css' />
|
||||
<script type='text/javascript' src='../lib/jquery-1.4.2.min.js'></script>
|
||||
<script type='text/javascript' src='lib/fancybox/jquery.fancybox-1.2.6.pack.js'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#fullcalendar-link').fancybox({
|
||||
|
@ -18,12 +16,12 @@
|
|||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<div id='content'>
|
||||
|
||||
<h1>FancyBox <em>v1.2.6</em></h1>
|
||||
|
||||
<p>
|
||||
<a id='fullcalendar-link' class="iframe" href="plain.html">Open a FullCalendar</a>
|
||||
<a id='fullcalendar-link' class='iframe' href='plain.html'>Open a FullCalendar</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
// set your time to Tehran time (GMT+03:30)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<script type='text/javascript'>DISABLE_FIREBUG_LITE=true</script>
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript' src='../src/gcal/_loader.js'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
var gcalFeed = $.fullCalendar.gcalFeed("http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic");
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
year: 2009,
|
||||
month: 10,
|
||||
date: 22,
|
||||
//year: 2009,
|
||||
//month: 10,
|
||||
//date: 22,
|
||||
//defaultView: 'agendaWeek', // error also occured with month view
|
||||
editable: true,
|
||||
events: "../examples/json-events.php"
|
||||
events: "../demos/json-events.php"
|
||||
});
|
||||
|
||||
$('#calendar').fullCalendar('option', 'height', $(window).height()-80);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||
<script type='text/javascript' src='loader.js'></script>
|
||||
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
721
tests/jquery-ui/jquery.ui.tabs.js
vendored
|
@ -1,721 +0,0 @@
|
|||
/*
|
||||
* jQuery UI Tabs 1.8.1
|
||||
*
|
||||
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://docs.jquery.com/UI/Tabs
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.core.js
|
||||
* jquery.ui.widget.js
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
var tabId = 0,
|
||||
listId = 0;
|
||||
|
||||
$.widget("ui.tabs", {
|
||||
options: {
|
||||
add: null,
|
||||
ajaxOptions: null,
|
||||
cache: false,
|
||||
cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
|
||||
collapsible: false,
|
||||
disable: null,
|
||||
disabled: [],
|
||||
enable: null,
|
||||
event: 'click',
|
||||
fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
|
||||
idPrefix: 'ui-tabs-',
|
||||
load: null,
|
||||
panelTemplate: '<div></div>',
|
||||
remove: null,
|
||||
select: null,
|
||||
show: null,
|
||||
spinner: '<em>Loading…</em>',
|
||||
tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
|
||||
},
|
||||
_create: function() {
|
||||
this._tabify(true);
|
||||
},
|
||||
|
||||
_setOption: function(key, value) {
|
||||
if (key == 'selected') {
|
||||
if (this.options.collapsible && value == this.options.selected) {
|
||||
return;
|
||||
}
|
||||
this.select(value);
|
||||
}
|
||||
else {
|
||||
this.options[key] = value;
|
||||
this._tabify();
|
||||
}
|
||||
},
|
||||
|
||||
_tabId: function(a) {
|
||||
return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
|
||||
this.options.idPrefix + (++tabId);
|
||||
},
|
||||
|
||||
_sanitizeSelector: function(hash) {
|
||||
return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
|
||||
},
|
||||
|
||||
_cookie: function() {
|
||||
var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + (++listId));
|
||||
return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
|
||||
},
|
||||
|
||||
_ui: function(tab, panel) {
|
||||
return {
|
||||
tab: tab,
|
||||
panel: panel,
|
||||
index: this.anchors.index(tab)
|
||||
};
|
||||
},
|
||||
|
||||
_cleanup: function() {
|
||||
// restore all former loading tabs labels
|
||||
this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')
|
||||
.find('span:data(label.tabs)')
|
||||
.each(function() {
|
||||
var el = $(this);
|
||||
el.html(el.data('label.tabs')).removeData('label.tabs');
|
||||
});
|
||||
},
|
||||
|
||||
_tabify: function(init) {
|
||||
|
||||
this.list = this.element.find('ol,ul').eq(0);
|
||||
this.lis = $('li:has(a[href])', this.list);
|
||||
this.anchors = this.lis.map(function() { return $('a', this)[0]; });
|
||||
this.panels = $([]);
|
||||
|
||||
var self = this, o = this.options;
|
||||
|
||||
var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
|
||||
this.anchors.each(function(i, a) {
|
||||
var href = $(a).attr('href');
|
||||
|
||||
// For dynamically created HTML that contains a hash as href IE < 8 expands
|
||||
// such href to the full page url with hash and then misinterprets tab as ajax.
|
||||
// Same consideration applies for an added tab with a fragment identifier
|
||||
// since a[href=#fragment-identifier] does unexpectedly not match.
|
||||
// Thus normalize href attribute...
|
||||
var hrefBase = href.split('#')[0], baseEl;
|
||||
if (hrefBase && (hrefBase === location.toString().split('#')[0] ||
|
||||
(baseEl = $('base')[0]) && hrefBase === baseEl.href)) {
|
||||
href = a.hash;
|
||||
a.href = href;
|
||||
}
|
||||
|
||||
// inline tab
|
||||
if (fragmentId.test(href)) {
|
||||
self.panels = self.panels.add(self._sanitizeSelector(href));
|
||||
}
|
||||
|
||||
// remote tab
|
||||
else if (href != '#') { // prevent loading the page itself if href is just "#"
|
||||
$.data(a, 'href.tabs', href); // required for restore on destroy
|
||||
|
||||
// TODO until #3808 is fixed strip fragment identifier from url
|
||||
// (IE fails to load from such url)
|
||||
$.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
|
||||
|
||||
var id = self._tabId(a);
|
||||
a.href = '#' + id;
|
||||
var $panel = $('#' + id);
|
||||
if (!$panel.length) {
|
||||
$panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
|
||||
.insertAfter(self.panels[i - 1] || self.list);
|
||||
$panel.data('destroy.tabs', true);
|
||||
}
|
||||
self.panels = self.panels.add($panel);
|
||||
}
|
||||
|
||||
// invalid tab href
|
||||
else {
|
||||
o.disabled.push(i);
|
||||
}
|
||||
});
|
||||
|
||||
// initialization from scratch
|
||||
if (init) {
|
||||
|
||||
// attach necessary classes for styling
|
||||
this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
|
||||
this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
|
||||
this.lis.addClass('ui-state-default ui-corner-top');
|
||||
this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
|
||||
|
||||
// Selected tab
|
||||
// use "selected" option or try to retrieve:
|
||||
// 1. from fragment identifier in url
|
||||
// 2. from cookie
|
||||
// 3. from selected class attribute on <li>
|
||||
if (o.selected === undefined) {
|
||||
if (location.hash) {
|
||||
this.anchors.each(function(i, a) {
|
||||
if (a.hash == location.hash) {
|
||||
o.selected = i;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
}
|
||||
if (typeof o.selected != 'number' && o.cookie) {
|
||||
o.selected = parseInt(self._cookie(), 10);
|
||||
}
|
||||
if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
|
||||
o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
|
||||
}
|
||||
o.selected = o.selected || (this.lis.length ? 0 : -1);
|
||||
}
|
||||
else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
|
||||
o.selected = -1;
|
||||
}
|
||||
|
||||
// sanity check - default to first tab...
|
||||
o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;
|
||||
|
||||
// Take disabling tabs via class attribute from HTML
|
||||
// into account and update option properly.
|
||||
// A selected tab cannot become disabled.
|
||||
o.disabled = $.unique(o.disabled.concat(
|
||||
$.map(this.lis.filter('.ui-state-disabled'),
|
||||
function(n, i) { return self.lis.index(n); } )
|
||||
)).sort();
|
||||
|
||||
if ($.inArray(o.selected, o.disabled) != -1) {
|
||||
o.disabled.splice($.inArray(o.selected, o.disabled), 1);
|
||||
}
|
||||
|
||||
// highlight selected tab
|
||||
this.panels.addClass('ui-tabs-hide');
|
||||
this.lis.removeClass('ui-tabs-selected ui-state-active');
|
||||
if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
|
||||
this.panels.eq(o.selected).removeClass('ui-tabs-hide');
|
||||
this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');
|
||||
|
||||
// seems to be expected behavior that the show callback is fired
|
||||
self.element.queue("tabs", function() {
|
||||
self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
|
||||
});
|
||||
|
||||
this.load(o.selected);
|
||||
}
|
||||
|
||||
// clean up to avoid memory leaks in certain versions of IE 6
|
||||
$(window).bind('unload', function() {
|
||||
self.lis.add(self.anchors).unbind('.tabs');
|
||||
self.lis = self.anchors = self.panels = null;
|
||||
});
|
||||
|
||||
}
|
||||
// update selected after add/remove
|
||||
else {
|
||||
o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
|
||||
}
|
||||
|
||||
// update collapsible
|
||||
this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');
|
||||
|
||||
// set or update cookie after init and add/remove respectively
|
||||
if (o.cookie) {
|
||||
this._cookie(o.selected, o.cookie);
|
||||
}
|
||||
|
||||
// disable tabs
|
||||
for (var i = 0, li; (li = this.lis[i]); i++) {
|
||||
$(li)[$.inArray(i, o.disabled) != -1 &&
|
||||
!$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
|
||||
}
|
||||
|
||||
// reset cache if switching from cached to not cached
|
||||
if (o.cache === false) {
|
||||
this.anchors.removeData('cache.tabs');
|
||||
}
|
||||
|
||||
// remove all handlers before, tabify may run on existing tabs after add or option change
|
||||
this.lis.add(this.anchors).unbind('.tabs');
|
||||
|
||||
if (o.event != 'mouseover') {
|
||||
var addState = function(state, el) {
|
||||
if (el.is(':not(.ui-state-disabled)')) {
|
||||
el.addClass('ui-state-' + state);
|
||||
}
|
||||
};
|
||||
var removeState = function(state, el) {
|
||||
el.removeClass('ui-state-' + state);
|
||||
};
|
||||
this.lis.bind('mouseover.tabs', function() {
|
||||
addState('hover', $(this));
|
||||
});
|
||||
this.lis.bind('mouseout.tabs', function() {
|
||||
removeState('hover', $(this));
|
||||
});
|
||||
this.anchors.bind('focus.tabs', function() {
|
||||
addState('focus', $(this).closest('li'));
|
||||
});
|
||||
this.anchors.bind('blur.tabs', function() {
|
||||
removeState('focus', $(this).closest('li'));
|
||||
});
|
||||
}
|
||||
|
||||
// set up animations
|
||||
var hideFx, showFx;
|
||||
if (o.fx) {
|
||||
if ($.isArray(o.fx)) {
|
||||
hideFx = o.fx[0];
|
||||
showFx = o.fx[1];
|
||||
}
|
||||
else {
|
||||
hideFx = showFx = o.fx;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset certain styles left over from animation
|
||||
// and prevent IE's ClearType bug...
|
||||
function resetStyle($el, fx) {
|
||||
$el.css({ display: '' });
|
||||
if (!$.support.opacity && fx.opacity) {
|
||||
$el[0].style.removeAttribute('filter');
|
||||
}
|
||||
}
|
||||
|
||||
// Show a tab...
|
||||
var showTab = showFx ?
|
||||
function(clicked, $show) {
|
||||
$(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
|
||||
$show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
|
||||
.animate(showFx, showFx.duration || 'normal', function() {
|
||||
resetStyle($show, showFx);
|
||||
self._trigger('show', null, self._ui(clicked, $show[0]));
|
||||
});
|
||||
} :
|
||||
function(clicked, $show) {
|
||||
$(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
|
||||
$show.removeClass('ui-tabs-hide');
|
||||
self._trigger('show', null, self._ui(clicked, $show[0]));
|
||||
};
|
||||
|
||||
// Hide a tab, $show is optional...
|
||||
var hideTab = hideFx ?
|
||||
function(clicked, $hide) {
|
||||
$hide.animate(hideFx, hideFx.duration || 'normal', function() {
|
||||
self.lis.removeClass('ui-tabs-selected ui-state-active');
|
||||
$hide.addClass('ui-tabs-hide');
|
||||
resetStyle($hide, hideFx);
|
||||
self.element.dequeue("tabs");
|
||||
});
|
||||
} :
|
||||
function(clicked, $hide, $show) {
|
||||
self.lis.removeClass('ui-tabs-selected ui-state-active');
|
||||
$hide.addClass('ui-tabs-hide');
|
||||
self.element.dequeue("tabs");
|
||||
};
|
||||
|
||||
// attach tab event handler, unbind to avoid duplicates from former tabifying...
|
||||
this.anchors.bind(o.event + '.tabs', function() {
|
||||
var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
|
||||
$show = $(self._sanitizeSelector(this.hash));
|
||||
|
||||
// If tab is already selected and not collapsible or tab disabled or
|
||||
// or is already loading or click callback returns false stop here.
|
||||
// Check if click handler returns false last so that it is not executed
|
||||
// for a disabled or loading tab!
|
||||
if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
|
||||
$li.hasClass('ui-state-disabled') ||
|
||||
$li.hasClass('ui-state-processing') ||
|
||||
self._trigger('select', null, self._ui(this, $show[0])) === false) {
|
||||
this.blur();
|
||||
return false;
|
||||
}
|
||||
|
||||
o.selected = self.anchors.index(this);
|
||||
|
||||
self.abort();
|
||||
|
||||
// if tab may be closed
|
||||
if (o.collapsible) {
|
||||
if ($li.hasClass('ui-tabs-selected')) {
|
||||
o.selected = -1;
|
||||
|
||||
if (o.cookie) {
|
||||
self._cookie(o.selected, o.cookie);
|
||||
}
|
||||
|
||||
self.element.queue("tabs", function() {
|
||||
hideTab(el, $hide);
|
||||
}).dequeue("tabs");
|
||||
|
||||
this.blur();
|
||||
return false;
|
||||
}
|
||||
else if (!$hide.length) {
|
||||
if (o.cookie) {
|
||||
self._cookie(o.selected, o.cookie);
|
||||
}
|
||||
|
||||
self.element.queue("tabs", function() {
|
||||
showTab(el, $show);
|
||||
});
|
||||
|
||||
self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
|
||||
|
||||
this.blur();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (o.cookie) {
|
||||
self._cookie(o.selected, o.cookie);
|
||||
}
|
||||
|
||||
// show new tab
|
||||
if ($show.length) {
|
||||
if ($hide.length) {
|
||||
self.element.queue("tabs", function() {
|
||||
hideTab(el, $hide);
|
||||
});
|
||||
}
|
||||
self.element.queue("tabs", function() {
|
||||
showTab(el, $show);
|
||||
});
|
||||
|
||||
self.load(self.anchors.index(this));
|
||||
}
|
||||
else {
|
||||
throw 'jQuery UI Tabs: Mismatching fragment identifier.';
|
||||
}
|
||||
|
||||
// Prevent IE from keeping other link focussed when using the back button
|
||||
// and remove dotted border from clicked link. This is controlled via CSS
|
||||
// in modern browsers; blur() removes focus from address bar in Firefox
|
||||
// which can become a usability and annoying problem with tabs('rotate').
|
||||
if ($.browser.msie) {
|
||||
this.blur();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// disable click in any case
|
||||
this.anchors.bind('click.tabs', function(){return false;});
|
||||
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var o = this.options;
|
||||
|
||||
this.abort();
|
||||
|
||||
this.element.unbind('.tabs')
|
||||
.removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
|
||||
.removeData('tabs');
|
||||
|
||||
this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
|
||||
|
||||
this.anchors.each(function() {
|
||||
var href = $.data(this, 'href.tabs');
|
||||
if (href) {
|
||||
this.href = href;
|
||||
}
|
||||
var $this = $(this).unbind('.tabs');
|
||||
$.each(['href', 'load', 'cache'], function(i, prefix) {
|
||||
$this.removeData(prefix + '.tabs');
|
||||
});
|
||||
});
|
||||
|
||||
this.lis.unbind('.tabs').add(this.panels).each(function() {
|
||||
if ($.data(this, 'destroy.tabs')) {
|
||||
$(this).remove();
|
||||
}
|
||||
else {
|
||||
$(this).removeClass([
|
||||
'ui-state-default',
|
||||
'ui-corner-top',
|
||||
'ui-tabs-selected',
|
||||
'ui-state-active',
|
||||
'ui-state-hover',
|
||||
'ui-state-focus',
|
||||
'ui-state-disabled',
|
||||
'ui-tabs-panel',
|
||||
'ui-widget-content',
|
||||
'ui-corner-bottom',
|
||||
'ui-tabs-hide'
|
||||
].join(' '));
|
||||
}
|
||||
});
|
||||
|
||||
if (o.cookie) {
|
||||
this._cookie(null, o.cookie);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
add: function(url, label, index) {
|
||||
if (index === undefined) {
|
||||
index = this.anchors.length; // append by default
|
||||
}
|
||||
|
||||
var self = this, o = this.options,
|
||||
$li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),
|
||||
id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);
|
||||
|
||||
$li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
|
||||
|
||||
// try to find an existing element before creating a new one
|
||||
var $panel = $('#' + id);
|
||||
if (!$panel.length) {
|
||||
$panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
|
||||
}
|
||||
$panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
|
||||
|
||||
if (index >= this.lis.length) {
|
||||
$li.appendTo(this.list);
|
||||
$panel.appendTo(this.list[0].parentNode);
|
||||
}
|
||||
else {
|
||||
$li.insertBefore(this.lis[index]);
|
||||
$panel.insertBefore(this.panels[index]);
|
||||
}
|
||||
|
||||
o.disabled = $.map(o.disabled,
|
||||
function(n, i) { return n >= index ? ++n : n; });
|
||||
|
||||
this._tabify();
|
||||
|
||||
if (this.anchors.length == 1) { // after tabify
|
||||
o.selected = 0;
|
||||
$li.addClass('ui-tabs-selected ui-state-active');
|
||||
$panel.removeClass('ui-tabs-hide');
|
||||
this.element.queue("tabs", function() {
|
||||
self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
|
||||
});
|
||||
|
||||
this.load(0);
|
||||
}
|
||||
|
||||
// callback
|
||||
this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
|
||||
return this;
|
||||
},
|
||||
|
||||
remove: function(index) {
|
||||
var o = this.options, $li = this.lis.eq(index).remove(),
|
||||
$panel = this.panels.eq(index).remove();
|
||||
|
||||
// If selected tab was removed focus tab to the right or
|
||||
// in case the last tab was removed the tab to the left.
|
||||
if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
|
||||
this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
|
||||
}
|
||||
|
||||
o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
|
||||
function(n, i) { return n >= index ? --n : n; });
|
||||
|
||||
this._tabify();
|
||||
|
||||
// callback
|
||||
this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
|
||||
return this;
|
||||
},
|
||||
|
||||
enable: function(index) {
|
||||
var o = this.options;
|
||||
if ($.inArray(index, o.disabled) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lis.eq(index).removeClass('ui-state-disabled');
|
||||
o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
|
||||
|
||||
// callback
|
||||
this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
|
||||
return this;
|
||||
},
|
||||
|
||||
disable: function(index) {
|
||||
var self = this, o = this.options;
|
||||
if (index != o.selected) { // cannot disable already selected tab
|
||||
this.lis.eq(index).addClass('ui-state-disabled');
|
||||
|
||||
o.disabled.push(index);
|
||||
o.disabled.sort();
|
||||
|
||||
// callback
|
||||
this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
select: function(index) {
|
||||
if (typeof index == 'string') {
|
||||
index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
|
||||
}
|
||||
else if (index === null) { // usage of null is deprecated, TODO remove in next release
|
||||
index = -1;
|
||||
}
|
||||
if (index == -1 && this.options.collapsible) {
|
||||
index = this.options.selected;
|
||||
}
|
||||
|
||||
this.anchors.eq(index).trigger(this.options.event + '.tabs');
|
||||
return this;
|
||||
},
|
||||
|
||||
load: function(index) {
|
||||
var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs');
|
||||
|
||||
this.abort();
|
||||
|
||||
// not remote or from cache
|
||||
if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {
|
||||
this.element.dequeue("tabs");
|
||||
return;
|
||||
}
|
||||
|
||||
// load remote from here on
|
||||
this.lis.eq(index).addClass('ui-state-processing');
|
||||
|
||||
if (o.spinner) {
|
||||
var span = $('span', a);
|
||||
span.data('label.tabs', span.html()).html(o.spinner);
|
||||
}
|
||||
|
||||
this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
|
||||
url: url,
|
||||
success: function(r, s) {
|
||||
$(self._sanitizeSelector(a.hash)).html(r);
|
||||
|
||||
// take care of tab labels
|
||||
self._cleanup();
|
||||
|
||||
if (o.cache) {
|
||||
$.data(a, 'cache.tabs', true); // if loaded once do not load them again
|
||||
}
|
||||
|
||||
// callbacks
|
||||
self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
|
||||
try {
|
||||
o.ajaxOptions.success(r, s);
|
||||
}
|
||||
catch (e) {}
|
||||
},
|
||||
error: function(xhr, s, e) {
|
||||
// take care of tab labels
|
||||
self._cleanup();
|
||||
|
||||
// callbacks
|
||||
self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
|
||||
try {
|
||||
// Passing index avoid a race condition when this method is
|
||||
// called after the user has selected another tab.
|
||||
// Pass the anchor that initiated this request allows
|
||||
// loadError to manipulate the tab content panel via $(a.hash)
|
||||
o.ajaxOptions.error(xhr, s, index, a);
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
}));
|
||||
|
||||
// last, so that load event is fired before show...
|
||||
self.element.dequeue("tabs");
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
abort: function() {
|
||||
// stop possibly running animations
|
||||
this.element.queue([]);
|
||||
this.panels.stop(false, true);
|
||||
|
||||
// "tabs" queue must not contain more than two elements,
|
||||
// which are the callbacks for the latest clicked tab...
|
||||
this.element.queue("tabs", this.element.queue("tabs").splice(-2, 2));
|
||||
|
||||
// terminate pending requests from other tabs
|
||||
if (this.xhr) {
|
||||
this.xhr.abort();
|
||||
delete this.xhr;
|
||||
}
|
||||
|
||||
// take care of tab labels
|
||||
this._cleanup();
|
||||
return this;
|
||||
},
|
||||
|
||||
url: function(index, url) {
|
||||
this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
|
||||
return this;
|
||||
},
|
||||
|
||||
length: function() {
|
||||
return this.anchors.length;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$.extend($.ui.tabs, {
|
||||
version: '1.8.1'
|
||||
});
|
||||
|
||||
/*
|
||||
* Tabs Extensions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Rotate
|
||||
*/
|
||||
$.extend($.ui.tabs.prototype, {
|
||||
rotation: null,
|
||||
rotate: function(ms, continuing) {
|
||||
|
||||
var self = this, o = this.options;
|
||||
|
||||
var rotate = self._rotate || (self._rotate = function(e) {
|
||||
clearTimeout(self.rotation);
|
||||
self.rotation = setTimeout(function() {
|
||||
var t = o.selected;
|
||||
self.select( ++t < self.anchors.length ? t : 0 );
|
||||
}, ms);
|
||||
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
var stop = self._unrotate || (self._unrotate = !continuing ?
|
||||
function(e) {
|
||||
if (e.clientX) { // in case of a true click
|
||||
self.rotate(null);
|
||||
}
|
||||
} :
|
||||
function(e) {
|
||||
t = o.selected;
|
||||
rotate();
|
||||
});
|
||||
|
||||
// start rotation
|
||||
if (ms) {
|
||||
this.element.bind('tabsshow', rotate);
|
||||
this.anchors.bind(o.event + '.tabs', stop);
|
||||
rotate();
|
||||
}
|
||||
// stop rotation
|
||||
else {
|
||||
clearTimeout(self.rotation);
|
||||
this.element.unbind('tabsshow', rotate);
|
||||
this.anchors.unbind(o.event + '.tabs', stop);
|
||||
delete this._rotate;
|
||||
delete this._unrotate;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 146 B After Width: | Height: | Size: 146 B |
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 388 B After Width: | Height: | Size: 388 B |
Before Width: | Height: | Size: 374 B After Width: | Height: | Size: 374 B |
Before Width: | Height: | Size: 147 B After Width: | Height: | Size: 147 B |
Before Width: | Height: | Size: 393 B After Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 142 B After Width: | Height: | Size: 142 B |
Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 556 B |