refactored js, split into more files (much more manageable). tested

This commit is contained in:
Adam Shaw 2010-09-18 22:54:35 -07:00
parent 91e436dc0a
commit e2dbcaf15d
135 changed files with 5005 additions and 5257 deletions

126
Makefile
View file

@ -1,69 +1,95 @@
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
VER = `cat version.txt`
changelog.txt \
MIT-LICENSE.txt \
GPL-LICENSE.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 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 "compressing js..."
@java -jar ${BUILD_DIR}/compiler.jar --js ${BUILD_DIR}/fullcalendar/fullcalendar.js \
> ${BUILD_DIR}/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..."
@cp -r ${OTHER_FILES} ${BUILD_DIR}/fullcalendar
@echo "zipping..."
@mv ${BUILD_DIR}/fullcalendar ${BUILD_DIR}/fullcalendar-${VER}
@cd ${BUILD_DIR}; for f in fullcalendar-*; do \
@ -74,7 +100,7 @@ zip:
@mkdir -p ${DIST_DIR}
@mv ${BUILD_DIR}/fullcalendar-${VER}.zip ${DIST_DIR}
@echo "done."
clean:
@rm -rf ${BUILD_DIR}/fullcalendar
@rm -rf ${BUILD_DIR}/fullcalendar-*

1
build/externs.js Normal file
View file

@ -0,0 +1 @@
var jQuery;

View file

@ -1,27 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,27 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,27 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,27 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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
View 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
View 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>

View file

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

View file

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 124 B

View file

Before

Width:  |  Height:  |  Size: 123 B

After

Width:  |  Height:  |  Size: 123 B

View file

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

Before

Width:  |  Height:  |  Size: 104 B

After

Width:  |  Height:  |  Size: 104 B

View file

Before

Width:  |  Height:  |  Size: 88 B

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -1,8 +1,12 @@
/*
* 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,18 +41,23 @@
.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.
* 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
*/
* 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
*/
/* 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; }

View file

@ -1,27 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,28 +1,14 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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='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() {

View file

@ -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>

View file

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -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
View 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
View 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
View 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'>&nbsp;</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
View 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);
}
})();

File diff suppressed because it is too large Load diff

View 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);
}
}

View 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
View 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'>&nbsp;</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'>&nbsp;</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'>&nbsp;</div></div></td>" +
"<th class='" + tm + "-state-default'>&nbsp;</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')) : '&nbsp;') +
"</th><td class='fc-slot" + i + ' ' +
tm + "-state-default'><div style='position:relative'>&nbsp;</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>&nbsp;</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);
}
}
}

View 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
View 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);
}
}

View 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
View 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'>&nbsp;</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'>&nbsp;</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
};
}
}

View 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
View 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);
}
}

View 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]
};
};
}

View 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);
}
}
});
}
}
}

View 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 = {};
};
}

View 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;
};
}

View 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());
}
}
}

View 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
View 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
View 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 */
}

View file

@ -1,10 +1,23 @@
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);
@ -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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#039;')
.replace(/"/g, '&quot;')
.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
View 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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#039;')
.replace(/"/g, '&quot;')
.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
View 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]{ '&#8212;'[ 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: '&nbsp;&#9668;&nbsp;',
next: '&nbsp;&#9658;&nbsp;',
prevYear: '&nbsp;&lt;&lt;&nbsp;',
nextYear: '&nbsp;&gt;&gt;&nbsp;',
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: '&nbsp;&#9658;&nbsp;',
next: '&nbsp;&#9668;&nbsp;',
prevYear: '&nbsp;&gt;&gt;&nbsp;',
nextYear: '&nbsp;&lt;&lt;&nbsp;'
},
buttonIcons: {
prev: 'circle-triangle-e',
next: 'circle-triangle-w'
}
};

6
src/gcal/_loader.js Normal file
View file

@ -0,0 +1,6 @@
startload();
js('gcal.js');
endload();

View file

@ -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
*

View file

@ -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'>&nbsp;</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'>&nbsp;</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
View 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) {

View file

@ -8,6 +8,9 @@
* Date: @DATE
*
*/
/* TODO: make font sizes look the same in all doctypes */
.fc,
@ -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 */
}

View file

@ -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]{ '&#8212;'[ 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: '&nbsp;&#9668;&nbsp;',
next: '&nbsp;&#9658;&nbsp;',
prevYear: '&nbsp;&lt;&lt;&nbsp;',
nextYear: '&nbsp;&gt;&gt;&nbsp;',
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: '&nbsp;&#9658;&nbsp;',
next: '&nbsp;&#9668;&nbsp;',
prevYear: '&nbsp;&gt;&gt;&nbsp;',
nextYear: '&nbsp;&lt;&lt;&nbsp;'
},
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);
if (res === undefined) {
res = r;
}
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');
}
}
});
@ -129,8 +28,9 @@ $.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;
});
}
// 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'>&nbsp;</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);
}
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();
});
return this;
};
/* 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 = [];
}
// function for adding/overriding defaults
function setDefaults(d) {
$.extend(true, defaults, d);
}
// TODO: if there is no start date, return false to indicate an invalid event

View file

@ -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) {

View file

@ -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);
});
}
}

View file

@ -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;
}

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -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',

View file

@ -1,30 +1,28 @@
<!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">
$(document).ready(function() {
$('#fullcalendar-link').fancybox({
frameWidth: 1100,
frameHeight: 800
});
});
</script>
<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({
frameWidth: 1100,
frameHeight: 800
});
});
</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>
</p>
<h1>FancyBox <em>v1.2.6</em></h1>
<p>
<a id='fullcalendar-link' class='iframe' href='plain.html'>Open a FullCalendar</a>
</p>
</div>
</body>

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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)

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -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");

View file

@ -1,19 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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);

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -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() {
@ -93,4 +93,4 @@
<body>
<div id="calendar"> </div>
</body>
</html>
</html>

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -1,8 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!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() {

View file

@ -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&#8230;</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);

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 146 B

View file

Before

Width:  |  Height:  |  Size: 144 B

After

Width:  |  Height:  |  Size: 144 B

View file

Before

Width:  |  Height:  |  Size: 388 B

After

Width:  |  Height:  |  Size: 388 B

View file

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View file

Before

Width:  |  Height:  |  Size: 147 B

After

Width:  |  Height:  |  Size: 147 B

View file

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View file

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 406 B

View file

Before

Width:  |  Height:  |  Size: 142 B

After

Width:  |  Height:  |  Size: 142 B

View file

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 556 B

Some files were not shown because too many files have changed in this diff Show more