summaryrefslogtreecommitdiff
path: root/assignment1
diff options
context:
space:
mode:
authorrekado <rekado@elephly.net>2013-03-31 22:38:16 +0800
committerrekado <rekado@elephly.net>2013-03-31 22:38:16 +0800
commit2a1c8c643c25db4c4c6c2ded728650071a911b9f (patch)
tree54ffa9b60bd255740c312f245db97c63fa78c86e /assignment1
parent46d59cd8cdfc2d86fe4c7a50c2dea85a3752edc9 (diff)
materials
Diffstat (limited to 'assignment1')
-rw-r--r--assignment1/materials/Adjucating Sustainability: New Zealands Environment Court.pdfbin0 -> 3802002 bytes
-rw-r--r--assignment1/materials/EAE_10E.pdfbin0 -> 6240472 bytes
-rw-r--r--assignment1/materials/EIA/Principles of IA_web.pdfbin0 -> 28184 bytes
-rw-r--r--assignment1/materials/EIA/follow-up.pdfbin0 -> 65659 bytes
-rw-r--r--assignment1/materials/EIA/scoping.pdfbin0 -> 181083 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background.html690
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript_data/image.jpgbin0 -> 3811 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA.html799
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript_data/image.jpgbin0 -> 2531 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts.html664
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript_data/image.jpgbin0 -> 3001 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice.html623
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript_data/image.jpgbin0 -> 3043 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process.html664
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Generalised-EIA.gifbin0 -> 8011 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/flvplayer.swfbin0 -> 2576 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript_data/image.jpgbin0 -> 3297 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA.html596
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/flvplayer.swfbin0 -> 2576 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript_data/image.jpgbin0 -> 2900 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary.html460
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript_data/image.jpgbin0 -> 2535 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction.html422
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript_data/image.jpgbin0 -> 2927 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems.html711
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/flvplayer.swfbin0 -> 2576 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript_data/image.jpgbin0 -> 2854 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation.html477
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript_data/image.jpgbin0 -> 4088 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations.html623
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript_data/image.jpgbin0 -> 2501 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System.html594
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript_data/image.jpgbin0 -> 3392 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/urchin.js695
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary.html416
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/Gvu-logo.gifbin0 -> 1376 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/RMIT.gifbin0 -> 1134 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/USP.gifbin0 -> 1830 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/builder.js136
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/challenge14
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/controls.js965
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/dragdrop.js974
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/e-201312.js13
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/effects.js1122
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/footer_link2.gifbin0 -> 583 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/logo.jpgbin0 -> 25524 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/moo.js133
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript.html12
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript_data/image.jpgbin0 -> 3407 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype.js131
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype_002.js4221
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/scriptaculous.js58
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/slider.js275
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/sound.js55
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/swfobject.js178
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu.js64
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu_logo_white.gifbin0 -> 1097 bytes
-rw-r--r--assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/urchin.js695
-rw-r--r--assignment1/materials/Green Book_Environmental Methods Review.pdfbin0 -> 1906976 bytes
-rw-r--r--assignment1/materials/RMA/key-facts-2010-11.pdfbin0 -> 842433 bytes
-rw-r--r--assignment1/materials/RMA/resource-consent-analysis-nov06.pdfbin0 -> 367345 bytes
-rw-r--r--assignment1/materials/RMA/rma-guide-aug06.pdfbin0 -> 1003504 bytes
-rw-r--r--assignment1/materials/SEA/SEA-comparison-scotland-new-zealand.pdfbin0 -> 159389 bytes
-rw-r--r--assignment1/materials/SEA/SEAPolicyLevel_MoECzech_2005.pdfbin0 -> 1231516 bytes
-rw-r--r--assignment1/materials/SEA/review-of-SEA-in-12-countries.pdfbin0 -> 305853 bytes
-rw-r--r--assignment1/materials/devolution.pdf17059
-rw-r--r--assignment1/materials/eia-international-law.pdfbin0 -> 156461 bytes
-rw-r--r--assignment1/materials/eia-retrospect-prospect.pdfbin0 -> 246171 bytes
-rw-r--r--assignment1/materials/impact-significance.pdfbin0 -> 871358 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/26.pdfbin0 -> 44448 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/27.pdfbin0 -> 46576 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/28.pdfbin0 -> 25832 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/29.pdfbin0 -> 45472 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/30.pdfbin0 -> 20680 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/31.pdfbin0 -> 41472 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/32.pdfbin0 -> 43840 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/33.pdfbin0 -> 40784 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/39.pdfbin0 -> 42768 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/40.pdfbin0 -> 72992 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/46.pdfbin0 -> 32768 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/GetPage(5).aspxbin0 -> 38256 bytes
-rw-r--r--assignment1/materials/implementing-sustainability/test.pdfbin0 -> 60704 bytes
-rw-r--r--assignment1/materials/institutional-framework-for-sustainability.pdfbin0 -> 2871735 bytes
-rw-r--r--assignment1/materials/nz-eia-simultaneous-preparation-and-review.pdfbin0 -> 299727 bytes
-rw-r--r--assignment1/materials/practitioners.pdfbin0 -> 989901 bytes
-rw-r--r--assignment1/materials/precautionary-principle-EIA.pdfbin0 -> 1029314 bytes
-rw-r--r--assignment1/materials/state-of-the-art-of-EIA.pdfbin0 -> 147380 bytes
-rw-r--r--assignment1/materials/state-of-the-art-of-policy-assessment.pdfbin0 -> 144149 bytes
-rw-r--r--assignment1/materials/state-of-the-art-sustainability-assessment.pdfbin0 -> 189636 bytes
352 files changed, 142396 insertions, 0 deletions
diff --git a/assignment1/materials/Adjucating Sustainability: New Zealands Environment Court.pdf b/assignment1/materials/Adjucating Sustainability: New Zealands Environment Court.pdf
new file mode 100644
index 0000000..9fbc9fd
--- /dev/null
+++ b/assignment1/materials/Adjucating Sustainability: New Zealands Environment Court.pdf
Binary files differ
diff --git a/assignment1/materials/EAE_10E.pdf b/assignment1/materials/EAE_10E.pdf
new file mode 100644
index 0000000..f9abba1
--- /dev/null
+++ b/assignment1/materials/EAE_10E.pdf
Binary files differ
diff --git a/assignment1/materials/EIA/Principles of IA_web.pdf b/assignment1/materials/EIA/Principles of IA_web.pdf
new file mode 100644
index 0000000..732ef19
--- /dev/null
+++ b/assignment1/materials/EIA/Principles of IA_web.pdf
Binary files differ
diff --git a/assignment1/materials/EIA/follow-up.pdf b/assignment1/materials/EIA/follow-up.pdf
new file mode 100644
index 0000000..21b25b8
--- /dev/null
+++ b/assignment1/materials/EIA/follow-up.pdf
Binary files differ
diff --git a/assignment1/materials/EIA/scoping.pdf b/assignment1/materials/EIA/scoping.pdf
new file mode 100644
index 0000000..a88d3da
--- /dev/null
+++ b/assignment1/materials/EIA/scoping.pdf
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background.html
new file mode 100644
index 0000000..9edb82e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background.html
@@ -0,0 +1,690 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-1 Background</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-1 Background Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=145">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 310px;">
+ <li class="page_item page-item-145 current_page_item"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-145">
+ <h1 class="storytitle">1-1 Background <a href="http://eia.unu.edu/course/?page_id=145" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>This topic introduces the concept of EIA and outlines its history,
+placing it within the current framework of sustainable development.
+Reference is made to:
+</p>
+<ul>
+<li>the purpose and aims of EIA;
+ </li>
+<li>the nature and scope of environmental issues and impacts;
+ </li>
+<li>the principles of EIA administration and practice;
+ </li>
+<li>the concept of integrated assessment;
+ </li>
+<li>the key elements of the EIA process;
+ </li>
+<li>the costs and benefits of undertaking EIA; and
+ </li>
+<li>the role of capacity building in improving EIA practice.
+ </li>
+</ul>
+<p><font size="3"><b>Learning Outcomes of this Section</b></font>
+</p>
+<p>On successful completion of this Section, you will be able to:
+</p>
+<ul>
+<li>Demonstrate an introductory understanding of EIA and why it is necessary;
+ </li>
+<li>Appreciate the worldwide influence of EIA practice.
+ </li>
+</ul>
+<p><font size="3"><b>Structure of these EIA learning materials</b></font>
+</p>
+<p>In this module, the EIA process is discussed in 11 Sections.
+Following this introductory section, Background (Section 1), are the
+following 10 Sections in order, with a brief description of the purpose
+of each stage in the EIA process:
+</p>
+<ul>
+<li>Law, Policy and Institutional Arrangements (Section 2): To provide
+regulatory and legislative governance structures and requirements of EIA
+ processes for project proponents, EIA practitioners and stakeholders.
+ </li>
+<li>Public involvement (Section 3): To inform the public about the
+proposal and to gain the inputs of those directly affected by or
+interested in the proposal. Public involvement in some form may occur
+throughout the EIA process, although it tends to be focused on scoping
+and review phases of EIA.
+ </li>
+<li>Screening (Section 4): To decide whether or not a proposal should be
+ subject to the EIA process and, if so, at what level of detail.
+ </li>
+<li>Scoping (Section 5): To identify the key issues and impacts that are
+ likely to require further investigation, and to prepare the terms of
+reference for the EIA study.
+ </li>
+<li>Impact analysis (Section 6): To identify and predict the likely
+environmental and social effects of the proposal and evaluate their
+significance.
+ </li>
+<li>Mitigation and impact management (Section 7): To develop measures to
+ avoid, reduce or compensate for impacts, making good any environmental
+damage.
+ </li>
+<li>Reporting (Section 8 ): To describe the results of the EIA for decision-makers and other interested parties.
+ </li>
+<li>Review of EIA quality (Section 9): To examine the adequacy of the
+EIA report to see if it meets the terms of reference and provides the
+information necessary for decision-making.
+ </li>
+<li>Decision-making (Section 10): To approve or reject the proposal and
+set the terms and conditions under which it can proceed. The
+decision-maker also has the option to defer approval (e.g. until certain
+ conditions are met or to require a proponent to redesign the project so
+ that the environmental effects are minimised).
+ </li>
+<li>Implementation and follow up (Section 11): To check on the
+implementation of the terms and conditions of approval during the
+construction and operation phases; to monitor the impacts of the project
+ and the effectiveness of mitigation measures; to take any actions
+necessary to ameliorate problems; and, as required, to undertake audit
+and evaluation to strengthen future EIA applications.
+ </li>
+</ul>
+<p>In this module you will be looking only at EIA. However, it is
+important to recognise that there is a general principle of assessment
+that applies to EIA, and to other assessment processes. There are
+several other processes that relate closely to the review of
+environmental impacts that may result from a proposed project. The
+following are well recognised processes:
+</p>
+<ul>
+<li>Social Impact Assessment
+ </li>
+<li>Risk Assessment
+ </li>
+<li>Life Cycle Analysis
+ </li>
+<li> Energy Analysis
+ </li>
+<li>Health Impact Assessment
+ </li>
+<li>Regulatory Impact Assessment
+ </li>
+<li>Species Impact Assessment
+ </li>
+<li>Technology Assessment
+ </li>
+<li>Economic Assessment
+ </li>
+<li>Cumulative Impact Assessment
+ </li>
+<li>Strategic Environmental Assessment
+ </li>
+<li>Integrated Impact Assessment
+ </li>
+</ul>
+<p>Some, like Energy Analysis, focus on a particular part of the
+environment. Others, like Life Cycle Analysis, enable the consideration
+of all those parts of the environment that are relevant to the
+assessment. Also, depending on how the terms, like health, are defined
+for the study you may find that it is covering most of the issues that
+would be found in an EIA. For example a Technology Assessment could
+include review of the impacts on ecosystems, air quality and the like.
+Similarly, if the definition of ‘environment’ is taken broadly for
+an EIA, then the EIA may cover the issues of the other assessment
+processes; for example:
+</p>
+<ul>
+<li>social aspects (such as impacts on employment, community interaction);
+ </li>
+<li>risks (such as threats to native animals, water supplies);
+ </li>
+<li>life cycle (such as the impacts at each stage of the project – design through to operation and closure); and
+ </li>
+<li>energy (such as use of non-renewable energy sources, Greenhouse gas emissions), etc
+ </li>
+</ul>
+<p>So there is the potential for a lot of connections between the
+different forms of assessment. The essential difference between them is
+how the terms, or scope of assessment, are defined – narrowly, or
+broadly. Otherwise they all follow the same general principle.
+</p>
+<p><font size="3"><b>Principle of Assessment</b></font>
+</p>
+<p>With all the assessment approaches noted above, they are designed to
+identify potential impacts of a development, action or project. To do
+this the assessor needs to use personal experience and the experiences
+of others (including available knowledge) to think broadly about the
+changes that are possible, and whether those impacts will be positive or
+ negative.
+</p>
+<p>Particular approaches emphasis specific types of impacts (i.e. on
+health, on social groups). All have basically the same approach,
+although each may have its own individual language and detailed
+techniques.
+</p>
+<p>Most of the assessment processes also include a second step. After
+identifying the impacts, they also consider what may be needed to avoid
+or reduce adverse impacts.
+</p>
+<p><font size="3"><b>Informal Assessments</b></font>
+</p>
+<p>In this module you will be looking at the EIA processes that are
+required by governments, or by organisations that provides funds for
+projects (such as the Work Bank). An EIA conducted under these processes
+ can be thought of as a ‘formal’ EIA, as it is required by formal
+legislation or other agreement.
+</p>
+<p>However, in addition there are many possibilities of conducting
+‘informal’ EIAs. This is especially the case where assessment is
+incorporated in internal processes of corporations. Informal EIA, such
+as the environment assessment associated with an Environmental
+Management Systems, requires identification and documentation of
+potential impacts, plus the reporting of how those impacts would be
+managed. No matter whether the assessment process is formal or informal,
+ or what terms are used, the same principle (above) is involved.
+</p>
+<p><font size="3"><b>Social and political nature of EIA</b></font>
+</p>
+<p>While EIA has been viewed as a technical process, it is inherently a
+political process. EIA evolved from the politics surrounding the impacts
+ that development projects were having on the environment. Once
+established it became dominated by technocratic approaches, which may
+lead to people ignoring social, political and economic conditions.
+However, EIA is political in terms of the way in which governments
+legislate for EIA, and the ways in which value judgments and political
+decisions, at the level of the individual, permeate virtually every
+element of EIA. A significant political issue is the choice of proposals
+ to which EIA is applied (this is at the ‘screening‘ stage; Section
+4). This can be a value judgement where one type of project requires an
+EIA, while others do not. Other value judgements come into decisions
+about what environmental issues should be covered in the EIA (scoping;
+Section 5), which pieces of information are included in the EIA Report
+(Section 8), and how the information is presented to the
+decision-makers.
+</p>
+<p>There are ‘checks and balances’ in the EIA process to moderate
+some of these influences, especially where the public has the chance to
+be involved (see Section 3). However, there are few opportunities
+through the stages in the EIA process for the public to be involved.
+Even when they have the opportunity, the public’s ability to be involved
+ in the EIA process has been limited by the resources available
+(especially time and expertise).
+</p>
+<p><font size="3"><b>Overview of issues</b></font>
+</p>
+<p>This module provides you with an introduction to the way in which EIA
+ operates. As a result the module focuses on the technical aspects of
+EIA to help you understand how to conduct an EIA.
+</p>
+<p>The module spends only very limited time discussing other assessment
+types, or the political nature of EIA. However, when you are engaged in
+the technical side of EIA you are encouraged to remember these issues as
+ they may have an effect on the way your EIA is undertaken, and its
+outcomes.
+</p>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">August 1, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — ralph @ 2:21 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=145#comments" title="Comment on 1-1 Background">Comments (10)</a> </div>
+
+</div>
+
+
+<h2 id="comments">10 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-34">
+ <p>I am really impressed with this OER. It is the best online
+educational resources I have ever come across. The design, arrangement
+and simplicity of the material is all superb. Rating 5 on 5</p>
+ <p><cite>Comment by R. A. Abang — February 20, 2007 @ <a href="#comment-34">10:02 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-262">
+ <p>This Course Module on EIA is of great value and interest and the principles will help in urban planing and urban administration.</p>
+ <p><cite>Comment by Constanza Noriega — April 10, 2007 @ <a href="#comment-262">10:22 am</a></cite> </p>
+ </li>
+
+ <li id="comment-283">
+ <p>Thanks for your positive comments. We appreciate them. </p>
+<p>How do you think we can made this open educational resource even better?</p>
+<p>Brendan Barrett</p>
+ <p><cite>Comment by brendan — April 16, 2007 @ <a href="#comment-283">1:29 am</a></cite> </p>
+ </li>
+
+ <li id="comment-23234">
+ <p>juz wanna say thank you for the info……..it really helps…</p>
+ <p><cite>Comment by JLYNPITH — October 30, 2008 @ <a href="#comment-23234">11:57 am</a></cite> </p>
+ </li>
+
+ <li id="comment-29456">
+ <p>De verdad,es muy util este curso,pero mas provechocos también a
+todos los hispanos parlantes y asi sería mas interesante,Atte,Javier
+Martínez Perú-Argentina</p>
+ <p><cite>Comment by JAVIER MARTINEZ — February 19, 2009 @ <a href="#comment-29456">7:31 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-41042">
+ <p>Hi there, like the others i wanted to say that this has been
+invaluable. im studying am module of this at university and these notes
+are alot clearer than the ones i received!</p>
+<p>To make it better – maybe off pdf version for download – as the flash
+ images are nice but difficult to copy the information to study?</p>
+<p>Also i saw you have an SEA section, but only by altering the url at
+the top did i find it – are there any links on this page for me to look
+at other courses you have?</p>
+<p>i think you should circulate this website to academics who can pass it on to students.. it is invaluable!</p>
+<p>many thanks<br>
+Jo</p>
+ <p><cite>Comment by Joanna Langhelt — May 18, 2010 @ <a href="#comment-41042">2:31 am</a></cite> </p>
+ </li>
+
+ <li id="comment-45288">
+ <p>gives us very valuable and useful informations</p>
+ <p><cite>Comment by keerthan — September 12, 2010 @ <a href="#comment-45288">6:32 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-81073">
+ <p>this is simple and is very useful for my studies especially when i am learning online </p>
+<p>cheers<br>
+John</p>
+ <p><cite>Comment by John — August 4, 2012 @ <a href="#comment-81073">4:58 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-97937">
+ <p>the document is verry intaresting for geography and environmental menagement students for the course EIA.</p>
+ <p><cite>Comment by wendafrash geremu — November 16, 2012 @ <a href="#comment-97937">4:58 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-108711">
+ <p>Very good information for EIA Students.</p>
+ <p><cite>Comment by M.A.BALAN NAIR — January 23, 2013 @ <a href="#comment-108711">2:42 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=145"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+ <a href="http://eia.unu.edu/course/wp-trackback.php?p=145" rel="trackback">TrackBack <abbr title="Uniform Resource Identifier">URI</abbr></a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="145" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-1%20Background_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'145'});
+var load_cmc = function(){linktracker_init(3787197,145,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript.html
new file mode 100644
index 0000000..2daeeba
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_Vuv3MQ7R7XN997rHbzfbo7bPwHA3oECrhDSXtOCFpbSl6CA8MaYsI4zeoou6xcEtT4A9m8vzjAy6Co7_N811dq5lhkAaXYrtiKdtuO9sP4jMKoVayISnUAJPN77A-VUpukYPhi65WOZDxYEAj5Oiui5JlUq25Hlh7xv0sdiphiQHjcOKmvo" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_Vuv3MQ7R7XN997rHbzfbo7bPwHA3oECrhDSXtOCFpbSl6CA8MaYsI4zeoou6xcEtT4A9m8vzjAy6Co7_N811dq5lhkAaXYrtiKdtuO9sP4jMKoVayISnUAJPN77A-VUpukYPhi65WOZDxYEAj5Oiui5JlUq25Hlh7xv0sdiphiQHjcOKmvo&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript_data/image.jpg
new file mode 100644
index 0000000..4225114
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-1 Background_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA.html
new file mode 100644
index 0000000..a23f068
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA.html
@@ -0,0 +1,799 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=93">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 310px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93 current_page_item"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-93">
+ <h1 class="storytitle">1-2 Purpose and aims of EIA <a href="http://eia.unu.edu/course/?page_id=93" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>Simply defined, EIA is a systematic process to identify, predict
+and evaluate the environmental effects of proposed actions and projects.
+ This process is applied prior to major decisions and commitments being
+made. A broad definition of environment is adopted. Whenever appropriate
+ social, cultural and health effects are considered as an integral part
+of EIA. Particular attention is given in EIA practice to preventing,
+mitigating and offsetting the significant adverse effects of proposed
+undertakings.
+</p>
+<p>The purpose of EIA is to:
+</p>
+<ul>
+<li>provide information for decision-making on the environmental consequences of proposed actions; and
+ </li>
+<li>promote environmentally sound and sustainable development through
+the identification of appropriate enhancement and mitigation measures.
+ </li>
+</ul>
+<p>Sustainable development is a key concept that has gained increasing
+international acceptance during the last two decades. A milestone in
+this process was the ‘Brundtland’ report, which defined sustainable
+development as ‘development that meets the needs of today’s
+generation without compromising those of future generations’. Five
+years later, the UN Conference on Environment and Development (UNCED),
+the Earth Summit, established a number of international agreements,
+declarations and commitments (see table below). Agenda 21, the global
+action plan for sustainable development, emphasises the importance of
+integrated environment and development decision-making and promotes the
+use of EIA and other policy instruments for this purpose.
+</p>
+<table>
+<caption><b>Four cornerstones of the Earth Summit</b></caption>
+<thead>
+<tr><th style="width: 40%; background-color: rgb(184, 193, 212);"><b>Cornerstone</b>
+ </th>
+<th style="width: 60%; background-color: rgb(143, 156, 184);"><b>Summary</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i></i><br>
+
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td><b>The Rio Declaration on Environment and Development</b>
+ </td>
+<td>A set of principles which provide guidance on achieving sustainable development.
+ </td>
+</tr>
+<tr>
+<td><b>Framework Convention on Climate Change</b>
+ </td>
+<td>An international treaty to stabilise greenhouse gas concentrations in the atmosphere.
+ </td>
+</tr>
+<tr>
+<td><b>Convention on Biological Diversity</b>
+ </td>
+<td>An international convention with three objectives: the conservation
+of biodiversity, the sustainable use of its components, and the
+equitable sharing of benefits from genetic resources.
+ </td>
+</tr>
+<tr>
+<td><b>Agenda 21</b>
+ </td>
+<td>A global programme of action for achieving sustainable development
+to which countries are ‘politically committed’ rather than legally
+obligated.
+ </td>
+</tr>
+</tbody>
+</table>
+<p><font size="3"><b>Perspectives on sustainable development</b></font>
+</p>
+<p>Sustainable development is an evolving concept, which is continually
+being redefined and reinterpreted. The starting point for most people is
+ the ‘Brundtland definition’ (described above), which also can be
+formally stated as twin principles of intra- and inter-generational
+equity. In practice, these principles mean improving the welfare of the
+world’s poor and maintaining the development opportunities for the
+generations that follow.
+</p>
+<p>The challenge of sustainable development may be summarised by comparing three overriding indicators:
+</p>
+<ul>
+<li>First, human activity is estimated to currently consume or pre-empt 40 per cent of net primary productivity on land.
+ </li>
+<li>Second, 60 per cent of the world’s population live close to or under the poverty line.
+ </li>
+<li>Third, the world’s population is projected to double by mid-century.
+ </li>
+</ul>
+<p>Without major policy and technology changes, UNEP and other
+institutions have concluded that such trends threaten the stability of
+the world community and the global environment.
+</p>
+<p><font size="3"><b>Why EIA is important</b></font>
+</p>
+<p>Reducing the burden of environmental impacts is necessary if
+development is to become sustainable. These impacts are more complex,
+larger in scale and further reaching in their potential consequences
+than thirty years ago when EIA was first introduced. As a result, EIA
+has become of ever increasing importance as a tool for development
+decision-making.
+</p>
+<p>This role is formally recognized in Principle 17 of the Rio Declaration on Environment and Development:
+</p>
+<blockquote><p>‘Environmental impact assessment, as a national
+instrument, shall be undertaken for proposed activities that are likely
+to have a&nbsp;significant adverse impact on the environment and are
+subject to a decision of a competent national authority’.
+</p></blockquote>
+<p>In practice, EIA is applied primarily to prevent or minimise the
+adverse effects of major development proposals, such as power stations,
+dams and reservoirs, industrial complexes, etc. It is also used as a
+planning tool to promote sustainable development by integrating
+environmental considerations into a wide range of proposed actions. Most
+ notably, strategic environmental assessment (SEA) of policies and plans
+ focuses on the highest levels of decision making, when better account
+can be taken of the environment in considering development alternatives
+and options. More limited forms of EIA can be used to ensure that
+smaller scale projects, conform to appropriate environmental standards
+or site and design criteria. Such projects include dredging activities,
+road realignment and upgrading, and housing subdivisions.
+</p>
+<p><font size="3"><b>What are the aims and objectives of EIA?</b></font>
+</p>
+<p>The aims and objectives of EIA can be divided into two categories.
+The immediate aim of EIA is to inform the process of decision-making by
+identifying the potentially significant environmental effects and risks
+of development proposals. The ultimate (long term) aim of EIA is to
+promote sustainable development by ensuring that development proposals
+do not undermine critical resource and ecological functions or the well
+being, lifestyle and livelihood of the communities and peoples who
+depend on them.
+</p>
+<p>Immediate objectives of EIA are to:
+</p>
+<ul>
+<li>improve the environmental design of the proposal;
+ </li>
+<li>ensure that resources are used appropriately and efficiently;
+ </li>
+<li>identify appropriate measures for mitigating the potential impacts of the proposal; and
+ </li>
+<li>facilitate informed decision making, including setting the environmental terms and conditions for implementing the proposal.
+ </li>
+</ul>
+<p>Long term objectives of EIA are to:
+</p>
+<ul>
+<li>protect human health and safety;
+ </li>
+<li>avoid irreversible changes and serious damage to the environment;
+ </li>
+<li>safeguard valued resources, natural areas and ecosystem components; and&nbsp;
+ </li>
+<li>enhance the social aspects of the proposal.
+ </li>
+</ul>
+<p><font size="3"><b>Limitations of EIA</b></font>
+</p>
+<p>EIA is also a way of ensuring that environmental factors are
+considered in decision-making process along with the traditional
+economic and technical factors. Importantly EIA requires the scientific
+(technical) and value issues to be dealt with in a single assessment
+process. This helps in the proper consideration of all advantages and
+disadvantages of a proposal. Environmental considerations may,
+therefore, be set aside in favour of what are felt to be more important
+considerations. Alternatively, predicted adverse effects on the
+environment might lead to strict conditions being imposed to avoid these
+ effects or remedy any adverse effects, or perhaps lead to the complete
+abandonment of a proposal.
+</p>
+<p>However, it is most important to recognise that EIA cannot be
+regarded as a means of introducing an environmental “veto” power into
+administrative decision-making processes. Decisions that are
+unsatisfactory from an environmental point of view can still be made,
+but with full knowledge of the environmental consequences. The final
+decision about a proposal depends upon the likely severity of the
+adverse effects, balanced against other expected benefits.
+</p>
+<p>In other words, EIA is an administrative process that identifies the
+potential environmental effects of undertaking a proposal, and presents
+these environmental effects alongside the other advantages and
+disadvantages of the proposal to the decision-makers. In the vast
+majority of EIA procedures this means that the outcome of the EIA
+process provides advice to the decision-makers – it does not provide a
+ final decision. So, by itself, the EIA procedures cannot be expected to
+ stop a proposal – although this is an outcome that some members of
+the general community and environment groups may expect.
+</p>
+<p>In summary then:
+</p>
+<ul>
+<li>only a very small fraction of proposals are halted, permanently or
+temporarily, as a direct result of EIA at the end of the review process;
+ </li>
+<li>preemption or early withdrawal of unsound proposals has been reported though it has proved difficult to document;
+ </li>
+<li>EIA has been useful in developing support for and confirmation of positive environmentally sound proposals;
+ </li>
+<li>the greening or environmental improvement of proposed activities is frequently seen; and
+ </li>
+<li>particular indirect effects of EIA are both instrumental (such as
+where policy or institutional adjustments are made as a result of EIA
+experience) and educational where participation in the EIA process leads
+ to positive changes in environmental attitudes and behavior.
+ </li>
+</ul>
+<p>With regard to the last point there is considerable advantage to the
+general community where those people involved with the proposal, as well
+ as decision-makers, are required to think about the environmental
+effects (and thence avoid negative effects), and the public can be made
+aware of the details of the proposal.
+</p>
+<p>The limited power of EIA may seem to greatly reduce its value.
+However, as you have seen there are many benefits that come from using
+EIA.
+</p>
+<p><font size="3"><b>Practical Examples and Case Studies</b></font>
+</p>
+<p>On the EIA wiki that accompanies this course module there are a large number of <a href="http://eia.unu.edu/wiki/index.php/Case_Studies">case studies</a> exploring EIA in practice. It is recommended that where possible you review these case studies and where possible add to them. </p>
+<p>Another very interesting resource is the online video documentary produced by Prof. Sharon Beder dealing with the EIA for the <a href="http://www.herinst.org/envcrisis/tunnel/contents.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.herinst.org');">Sydney Harbour Tunnel</a> in Australia.
+</p>
+<p> </p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — brendan @ 11:43 am </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=93#comments" title="Comment on 1-2 Purpose and aims of EIA">Comments (27)</a> </div>
+
+</div>
+
+
+<h2 id="comments">27 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-624">
+ <p>This material is so helpful. Keep up the good work</p>
+ <p><cite>Comment by hilda mensah — May 25, 2007 @ <a href="#comment-624">5:34 am</a></cite> </p>
+ </li>
+
+ <li id="comment-3738">
+ <p>Your website is great! It provides us easy access to up-to-date and
+useful information on practically all topics in environment and gender.
+Thank you so much.</p>
+ <p><cite>Comment by <a href="http://cssac/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/CSSAC');" rel="external nofollow" class="url">Cely Salazar Binoya, Ph.D0.</a> — February 1, 2008 @ <a href="#comment-3738">7:51 am</a></cite> </p>
+ </li>
+
+ <li id="comment-3739">
+ <p>The EIA material is very helpful. Thanks a lot</p>
+ <p><cite>Comment by <a href="http://cssac/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/CSSAC');" rel="external nofollow" class="url">Cely Salazar Binoya, Ph.D.</a> — February 1, 2008 @ <a href="#comment-3739">7:54 am</a></cite> </p>
+ </li>
+
+ <li id="comment-6684">
+ <p>its a very very nice web site ita realy help me now to solve any
+problem in my assignment i m very thanksfull to the publishers of this
+site and god bless u</p>
+ <p><cite>Comment by ahsan hu university — May 17, 2008 @ <a href="#comment-6684">2:54 am</a></cite> </p>
+ </li>
+
+ <li id="comment-9767">
+ <p>I have been looking for information on EIA practice and was glad to
+have eventually come across such a great site. Thank you so much, you
+made my day</p>
+ <p><cite>Comment by Lineekela — July 17, 2008 @ <a href="#comment-9767">8:02 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-11868">
+ <p>This doc will help me a lot in doing EIA here in the Philippines. I will share this with my students</p>
+ <p><cite>Comment by Carmie Liwag — August 12, 2008 @ <a href="#comment-11868">8:51 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-23908">
+ <p>Very clear and cohesive, thank you!</p>
+ <p><cite>Comment by Jesse — November 6, 2008 @ <a href="#comment-23908">5:55 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-24458">
+ <p>This the first time I have opened this website but have found it to
+be user friendly, detailed in substance, I have decided to term it a
+goldmine to the student, practitioner, lecturer and anybody who would
+like to enrich their knowledge about EIA.</p>
+ <p><cite>Comment by Magghangwe Alfred — November 12, 2008 @ <a href="#comment-24458">5:21 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-30472">
+ <p>Thank you alot for the lecture notes on EIA.It is helpfull to me.<br>
+May our ALMIGHTY GOD BLESS YOU.</p>
+ <p><cite>Comment by engera mambore — April 1, 2009 @ <a href="#comment-30472">12:28 am</a></cite> </p>
+ </li>
+
+ <li id="comment-31259">
+ <p>Thank you!!! v. useful for my uni coursework, had all the info needed! like no other website i could find!<br>
+Thank you again!!</p>
+ <p><cite>Comment by Roxy — April 20, 2009 @ <a href="#comment-31259">2:45 am</a></cite> </p>
+ </li>
+
+ <li id="comment-32554">
+ <p>The information on this site was very useful to me.</p>
+ <p><cite>Comment by Alandia — June 28, 2009 @ <a href="#comment-32554">4:59 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-32739">
+ <p>this is first after working 6 years in EIa i knew all about tha eia through this thanks</p>
+ <p><cite>Comment by G. Ponnusamy — July 21, 2009 @ <a href="#comment-32739">1:59 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-41410">
+ <p>good notes with world wide understandable english</p>
+ <p><cite>Comment by <a href="http://www.yahoo.com/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/www.yahoo.com');" rel="external nofollow" class="url">Magdalena Raymond</a> — June 4, 2010 @ <a href="#comment-41410">12:24 am</a></cite> </p>
+ </li>
+
+ <li id="comment-45676">
+ <p>can you please elaborate the key environmental parameters that are assessed when determining a suitable site for a clinic?</p>
+ <p><cite>Comment by sephule — October 7, 2010 @ <a href="#comment-45676">4:38 am</a></cite> </p>
+ </li>
+
+ <li id="comment-45994">
+ <p>these are very good notes they give a very clear understanding of
+the purpose as well as the aims of environmental impact assessment</p>
+ <p><cite>Comment by <a href="http://webmail/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/webmail');" rel="external nofollow" class="url">Y NOPOTSO</a> — October 22, 2010 @ <a href="#comment-45994">11:46 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-50249">
+ <p>at first i couldnt believe but after reviewing some notes i realize
+that this could be help full from the bigginers to the higher level
+student, researcher, practitioner, lecturer, proffesors and interested
+stakeholders!</p>
+ <p><cite>Comment by Mathayo BARIKIEL — March 5, 2011 @ <a href="#comment-50249">7:42 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-52098">
+ <p>Thank you so very much on this, most superb, presentation.</p>
+<p>I am using this to supplement my studies in EIA. It is really helpful.</p>
+<p>Cheers.</p>
+ <p><cite>Comment by Predrag — April 22, 2011 @ <a href="#comment-52098">5:57 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-52713">
+ <p>EIA should always be an integral part of every scientific study as we try to cope up with recurrent global climatic changes.<br>
+I’ve found the study extra beneficial</p>
+ <p><cite>Comment by <a href="http://mozillafirefox/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/mozillafirefox');" rel="external nofollow" class="url">hobic</a> — May 8, 2011 @ <a href="#comment-52713">5:57 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-52714">
+ <p>found it interesting. EIA should be an integral topic of every scientific study</p>
+ <p><cite>Comment by <a href="http://mozillafirefox/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/mozillafirefox');" rel="external nofollow" class="url">hobic</a> — May 8, 2011 @ <a href="#comment-52714">5:59 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-58051">
+ <p>EIA can be used by in rural areas if yes how? since im care iwould
+like to know about the application if EIAs to the development. can
+community assess the proposed development on their own? thanks for this
+opportunity i will always getting involve.</p>
+ <p><cite>Comment by jali mh — September 13, 2011 @ <a href="#comment-58051">5:57 am</a></cite> </p>
+ </li>
+
+ <li id="comment-59588">
+ <p>This material is very helpfull. I was about to go write my exam on
+Environmental Management course and had a quick glance at your website
+and it really helped me alot. Thanks</p>
+ <p><cite>Comment by Shoes — November 11, 2011 @ <a href="#comment-59588">7:39 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-60026">
+ <p>This material is very brief and concise, I really love it . Keep it up</p>
+ <p><cite>Comment by Michael Acquah — December 1, 2011 @ <a href="#comment-60026">5:45 am</a></cite> </p>
+ </li>
+
+ <li id="comment-61548">
+ <p>the material is so interesting that every one can get useful information regarding to EIA. </p>
+<p> THANK U!!!!!!!!!!</p>
+ <p><cite>Comment by minuye hailu — February 6, 2012 @ <a href="#comment-61548">7:22 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-61875">
+ <p>Thank you very much, i have got all the info needed for my assignment.<br>
+Its the best web site in internet</p>
+ <p><cite>Comment by chaitanya madhunapantula — February 21, 2012 @ <a href="#comment-61875">3:30 am</a></cite> </p>
+ </li>
+
+ <li id="comment-63519">
+ <p>improving decision on environment there should be an inforcement on EIA</p>
+ <p><cite>Comment by <a href="http://nil/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/nil');" rel="external nofollow" class="url">meshack osiah</a> — May 3, 2012 @ <a href="#comment-63519">12:50 am</a></cite> </p>
+ </li>
+
+ <li id="comment-96819">
+ <p>Thanks for your information on EIA , i would like to request sample
+reports on all EIA procedures specifically starting with Project
+registration report/document, Project Brief report, Scooping Report, EIA
+ final report and Non-Executive summary report on either Road project or
+ mining project.It will be very helpful to me once you send.</p>
+<p>Thanks for your time and consideration.<br>
+Meshack Osiah</p>
+ <p><cite>Comment by Meshack Osiah — November 10, 2012 @ <a href="#comment-96819">6:12 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-106207">
+ <p>I have been looking for information on EIA practice and was glad to
+have eventually come across such a great site. Thank you so much,</p>
+ <p><cite>Comment by <a href="http://www.squidoo.com/all-about-writing-essay" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/www.squidoo.com');" rel="external nofollow" class="url">definition essay topics</a> — January 7, 2013 @ <a href="#comment-106207">2:33 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=93"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="93" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-2%20Purpose%20and%20aims%20of%20EIA_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'93'});
+var load_cmc = function(){linktracker_init(3787197,93,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript.html
new file mode 100644
index 0000000..3dc7c42
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuvYztjIbnejptRxfs1oe6HTzzNWKRT4EtY3kFkQ0dzFBmOjI1L0lJ0Wu9otkLpInBn0ouDnztNmqblHSzrieBrRsatqulBb68jHFHaCwtB9c0jKMbEtqQ5AW2QVLy7-17-gIQk3oIDJqmAE8glY-YbxBdy4SIvEwBfnjp95qSQtXvt2W1s" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuvYztjIbnejptRxfs1oe6HTzzNWKRT4EtY3kFkQ0dzFBmOjI1L0lJ0Wu9otkLpInBn0ouDnztNmqblHSzrieBrRsatqulBb68jHFHaCwtB9c0jKMbEtqQ5AW2QVLy7-17-gIQk3oIDJqmAE8glY-YbxBdy4SIvEwBfnjp95qSQtXvt2W1s&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript_data/image.jpg
new file mode 100644
index 0000000..632730d
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-2 Purpose and aims of EIA_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts.html
new file mode 100644
index 0000000..7bf8cf0
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts.html
@@ -0,0 +1,664 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts </title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=97">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 310px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97 current_page_item"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-97">
+ <h1 class="storytitle">1-3 Nature and Scope of environmental issues and impacts <a href="http://eia.unu.edu/course/?page_id=97" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>Numerous reports on the state of the world indicate the
+environmental problems facing society. The Global Environmental Outlook
+(GEO) prepared by UNEP provides an authoritative statement of the major
+issues and their regional variations. In the GEO-2000 report, UNEP
+advises that ‘full scale emergencies now exist on a number of
+issues’, including water scarcity, land degradation, tropical forest
+clearance, species loss and climate warming. Some of these issues, such
+as climate warming and biodiversity loss, are global or so pervasive
+that they affect all countries. Other environmental problems are
+concentrated regionally and thus affect only certain countries or are
+more serious for some than others.
+</p>
+<p>The major environmental challenges facing different parts of the
+world are listed in the table below. This sample is a starting point for
+ discussion by participants to verify and identify regional and local
+examples that are of most relevance to their country, taking account of
+both current issues and future trends. For example, many small island
+states and delta regions of larger countries are vulnerable to natural
+hazards and threatened by sea level rise due to climate warming. Other
+countries are likely to experience increases in water scarcity and
+associated environmental stresses as a result of climate change.
+</p>
+<table>
+<caption><b>Major environmental issues in developing regions </b></caption>
+<thead>
+<tr><th style="width: 20%; background-color: rgb(184, 193, 212);"><b>Developing Countries</b>
+ </th>
+<th style="width: 80%; background-color: rgb(143, 156, 184);"><b>Major Environmental Issues</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i>Sources: UNEP, 1999; World Bank, 2000. </i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>Africa
+ </td>
+<td>The continent has the world’s poorest and most resource dependent
+population. It also carries the highest health burden due to severe
+environmental problems. These include desertification and soil
+degradation, declining food security, and increasing water scarcity and
+stress in north, east and southern Africa.
+ </td>
+</tr>
+<tr>
+<td>Asia and the Pacific
+ </td>
+<td>The region has high population densities in Southern and South East
+Asia. Rapid economic growth, urbanisation and industrialisation have
+helped in poverty alleviation but also increased pressure on land and
+water resources, widespread environmental degradation and high pollution
+ levels. Mega- cities are a particular focus of environmental and health
+ concerns.
+ </td>
+</tr>
+<tr>
+<td>Eastern Europe and Central Asia
+ </td>
+<td>Despite progress with economic restructuring and environmental clean
+ up, there is a legacy of industrial pollution and contaminated land. In
+ many areas, emissions of particulates, SO2, lead, heavy metals and
+toxic chemicals continue to expose the residents to health risks, and,
+in the Balkans, war and regional conflict have exacted a heavy
+environmental and social toll.
+ </td>
+</tr>
+<tr>
+<td>Latin America and the Caribbean
+ </td>
+<td>Approximately three-quarters of the population live in urban areas.
+Many cities are poor, overcrowded, polluted and lack basic
+infrastructure. The major green issue is the destruction of tropical
+forests and consequent loss of biodiversity, which is especially serious
+ in the Amazon basin.
+ </td>
+</tr>
+<tr>
+<td>Middle East
+ </td>
+<td>Most land is either subject to desertification or vulnerable to
+deterioration from saline, alkaline and/or nutrient deposition. Water
+resources are under severe pressure and groundwater sources are in a
+critical condition. Rapid and uncontrolled urbanisation has caused
+worsening air and water pollution in urban centres.
+ </td>
+</tr>
+</tbody>
+</table>
+<p>Another way of subdividing environmental issues is to group them
+under ‘green’ and ‘brown’ agendas. The green agenda focuses on
+natural resource management and environmental protection issues, such as
+ rural land and water use, forestry and fisheries and habitat and
+species conservation. The brown agenda is concerned with issues of
+industrial pollution, waste management and urban development.
+</p>
+<p>When undertaking EIA, a comprehensive view should be taken of the
+linkages and interactions among the issues under review. Also, the EIA
+should identify both the benefits and costs of development. In practice,
+ EIA often focuses on the adverse environmental impacts of proposed
+actions. This is done by reference to certain key characteristics, which
+ establish the potentially significant effects (see the table below).
+</p>
+<p>The impacts of a development proposal examined in EIA can be direct,
+such as the effect of toxic discharge on air and water quality, or
+indirect, such as the effect on human health from exposure to
+particulates or contaminants, which have built up in food chains. Other
+environmental and social impacts are induced, for example by a new road
+opening up an undeveloped area to subsequent settlement or by
+involuntary resettlement of people displaced by the construction of a
+large reservoir. Certain adverse impacts may appear relatively
+insignificant when considered in the context of an individual action or
+proposal but have a cumulative effect on the environment when added to
+all other actions and proposals; for example, deforestation resulting
+from plot by plot clearance for subsistence agriculture. A fuller
+discussion of environmental impacts and their analysis can be found in
+Section 6 – Impact analysis.
+</p>
+<table>
+<caption><b>Typology of environmental impacts</b></caption>
+<thead>
+<tr><th style="width: 50%; background-color: rgb(184, 193, 212);"><b>Category of Impacts</b>
+ </th>
+<th style="width: 50%; background-color: rgb(143, 156, 184);"><b>Types of Impacts</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i></i><br>
+
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>type
+ </td>
+<td>biophysical, social, health or economic
+ </td>
+</tr>
+<tr>
+<td>nature
+ </td>
+<td>direct or indirect, cumulative, etc.
+ </td>
+</tr>
+<tr>
+<td>magnitude or severity
+ </td>
+<td>high, moderate, low
+ </td>
+</tr>
+<tr>
+<td>extent
+ </td>
+<td>local, regional, transboundary or global
+ </td>
+</tr>
+<tr>
+<td>timing
+ </td>
+<td>immediate/long term
+ </td>
+</tr>
+<tr>
+<td>duration
+ </td>
+<td>temporary/permanent
+ </td>
+</tr>
+<tr>
+<td>uncertainty
+ </td>
+<td>low likelihood/high probability
+ </td>
+</tr>
+<tr>
+<td>reversibility
+ </td>
+<td>reversible/irreversible
+ </td>
+</tr>
+<tr>
+<td>significance*
+ </td>
+<td>unimportant/important
+ </td>
+</tr>
+</tbody>
+</table>
+<p><i>*Impact significance is not necessarily related to the impact
+magnitude. Sometimes very small impacts, such as the disturbance of the
+nest of a pair of endangered birds, may be significant. When determining
+ the significance of the potential impacts of a proposal, all of the
+above factors should be taken into consideration.</i>
+</p>
+<p><i></i> More detail on impact assessment is contained in Section 6.
+</p>
+<p>In many early examples of EIA practice, only the biophysical impacts
+of proposals were considered (such as effects on air and water quality,
+flora and fauna, noise levels, climate and hydrological systems).
+Increasingly EIA processes are used to analyse a range of impact types
+within a single framework. These include social, health, and economic
+aspects.
+</p>
+<p>However this trend toward integrated assessment for decision-making
+is by no means universal or uniform. Even in EIA systems where this
+trend is well established, the degree and extent of integration varies
+with legal requirements and accepted practice. In some countries, social
+ impacts are not assessed or are given only limited consideration. In
+other countries, EIAs are supplemented by related, but separate studies
+of social and health impacts.
+</p>
+<p>Despite a lack of internationally consistent practice, integrated
+impact assessment, linking biophysical and socio-economic effects, is
+identified as an important priority in Agenda 21. As a widely adopted
+process that already covers other impacts, EIA is recognised as one of
+the best available mechanisms for implementing an integrated approach.
+In practice, achieving this approach will require greater attention to
+be given to the identification of social, health and other impacts in
+the EIA process. This aspect is addressed further in Section 6 –
+Impact analysis.
+</p>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 11:56 am </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=97#comments" title="Comment on 1-3 Nature and Scope of environmental issues and impacts">Comments (5)</a> </div>
+
+</div>
+
+
+<h2 id="comments">5 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-28003">
+ <p>May i please ask for the author of this article as i would like to reference some material. Thank you for the information given.</p>
+ <p><cite>Comment by <a href="http://eia.unu.edu/course/?page_id=97" rel="external nofollow" class="url">Kelvin</a> — January 9, 2009 @ <a href="#comment-28003">3:45 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-28191">
+ <p>Dear Kelvin,</p>
+<p>The authors are United Nations University, RMIT University, and the United Nations Environment Programme (UNEP).</p>
+<p>Please just provide the link to this page in your reference, with a note on the date that you visited the site.</p>
+<p>Brendan Barrett<br>
+United Nations University</p>
+ <p><cite>Comment by brendan — January 15, 2009 @ <a href="#comment-28191">9:31 am</a></cite> </p>
+ </li>
+
+ <li id="comment-31773">
+ <p>Can I ask about your courses, please? I am currently just finishing
+ my BA at Sunshine Coast Uni, with dual majors of Communication and
+Sustainability, and Environmental Planning minor. I am most interested
+in Social Impact Assessment as a post grad qualificiation. Many thanks,
+ Georgie Bull</p>
+ <p><cite>Comment by Georgie Bull — May 1, 2009 @ <a href="#comment-31773">1:07 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-31864">
+ <p>This is an open educational resource used to support teaching and
+self learning. At present, it is being used in courses offered by Oxford
+ Brookes University (UK), McGill University (Canada) and Agder
+University (Norway). At least, those are the ones I know about and there
+ could be more. You would need to contact them directly for more
+information.</p>
+ <p><cite>Comment by brendan — May 6, 2009 @ <a href="#comment-31864">1:14 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-40690">
+ <p>Thanks for the good work. You are blessed</p>
+ <p><cite>Comment by Inyambe Wogar — April 29, 2010 @ <a href="#comment-40690">10:35 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=97"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="97" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-3%20Nature%20and%20Scope%20of%20environmental%20issues%20and%20impacts_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'97'});
+var load_cmc = function(){linktracker_init(3787197,97,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript.html
new file mode 100644
index 0000000..3378c5d
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuumLTMCqAffsqbrjokyOIrBvVW9D2hIewugyD1K5Q_SYSt-FZDFbfW0uMGf3lWhW9kuusPljR-B9urYOOFGXJpjpoTjDpZoQCTT2HDeNbBB3Ng84g6R6YC6Siv3B5BuoiKCNtWvgkivIn5iVQ6nlreAx7jOAI99oeHrRTmE75hHBg6ly84" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuumLTMCqAffsqbrjokyOIrBvVW9D2hIewugyD1K5Q_SYSt-FZDFbfW0uMGf3lWhW9kuusPljR-B9urYOOFGXJpjpoTjDpZoQCTT2HDeNbBB3Ng84g6R6YC6Siv3B5BuoiKCNtWvgkivIn5iVQ6nlreAx7jOAI99oeHrRTmE75hHBg6ly84&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript_data/image.jpg
new file mode 100644
index 0000000..475b8de
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-3 Nature and Scope of environmental issues and impacts_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice.html
new file mode 100644
index 0000000..42b3e45
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice.html
@@ -0,0 +1,623 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=100">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 322px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100 current_page_item"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-100">
+ <h1 class="storytitle">1-4 Principles of EIA administration and practice <a href="http://eia.unu.edu/course/?page_id=100" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>EIA is one of a number of policy tools that are used to evaluate
+project proposals. It is also a relatively recent development when
+compared to use of economic appraisal methods. A number of factors led
+to the introduction of EIA in the US National Environmental Policy Act
+(NEPA, 1969), including public concern about the quality of the
+environment and the increasing effects of new technologies and
+ever-larger development schemes. In addition, then available economic
+appraisal techniques, such as benefit cost analysis, did not take
+account of the environmental and social impacts of major projects.
+</p>
+<p>The architects of NEPA intended the environmental impact statement to
+ be the ‘action-forcing’ mechanism, which would change the way
+government decisions were made in the USA. However, they probably did
+not foresee the extent to which EIA would be adopted internationally,
+culminating in Principle 17 of the Rio Declaration on Environment and
+Development. Today, EIA is applied in more than 100 countries, and by
+all development banks and most international aid agencies. EIA has also
+evolved significantly, driven by improvements in law, procedure and
+methodology. Major trends in EIA process development are summarised in
+table below. Except for the early pioneers, the phases and timescales
+identified in the table below do not necessarily correspond to the
+development of EIA in particular countries. In all countries more
+strategic, sustainability- based approaches are still at a relatively
+early stage.
+</p>
+<table>
+<caption><b>Major trends in EIA</b></caption>
+<thead>
+<tr><th style="width: 20%;"><b>Phase</b>
+ </th>
+<th style="width: 20%;"><b>Time</b>
+ </th>
+<th style="width: 60%;"><b>Key Events</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="3"><i>Source: updated and amended from Sadler, 1996 </i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>Introduction and early development
+ </td>
+<td>1970-1975
+ </td>
+<td>Mandate and foundations of EIA established in the USA; then adopted
+by a few other countries (e.g. Australia, Canada, New Zealand); basic
+concept, procedure and methodology still apply.
+ </td>
+</tr>
+<tr>
+<td>Increasing scope and sophistication
+ </td>
+<td>mid ’70s to early ’80s
+ </td>
+<td>More advanced techniques (e.g. risk assessment); guidance on process
+ implementation (e.g. screening and scoping); social impacts considered;
+ public inquiries and reviews drive innovations in leading countries;
+take up of EIA still limited but includes developing countries (e.g.
+China, Thailand and the Philippines).
+ </td>
+</tr>
+<tr>
+<td>Process strengthening and integration
+ </td>
+<td>early ‘80’s to early ’90s
+ </td>
+<td>Review of EIA practice and experience; scientific and institutional
+frameworks of EIA updated; coordination of EIA with other processes,
+(e.g. project appraisal, land use planning); ecosystem- level changes
+and cumulative effects begin to be addressed; attention given to
+monitoring and other follow-up mechanisms. Many more countries adopt
+EIA; the European Community and the World Bank respectively establish
+supra-national and international lending requirements.
+ </td>
+</tr>
+<tr>
+<td>Strategic and sustainability orientation
+ </td>
+<td>early ’90s to date
+ </td>
+<td>EIA aspects enshrined in international agreements (see Section 2 –
+ Law, policy and institutional arrangements); marked increase in
+international training, capacity &amp; building and networking
+activities; development of strategic environmental assessment (SEA) of
+policies and plans; inclusion of sustainability concepts and criteria in
+ EIA and SEA practice; EIA applied in all OECD countries and large
+number of developing and transitional countries.
+ </td>
+</tr>
+</tbody>
+</table>
+<p>To date, EIA has been applied primarily at the project-level. This
+‘first generation’ process is now complemented by SEA of policies,
+plans and programmes, and both EIA and SEA are being adapted to bring a
+greater measure of ‘sustainability assurance’ to development
+decision making. These trends have brought new perspectives on what
+constitutes EIA good practice and effective performance.
+</p>
+<p>Recently, a number of reviews of these issues have been undertaken,
+including the International Study of the Effectiveness of Environmental
+Assessment (see Section A). It described basic and operational
+principles for the main steps and activities undertaken in the EIA
+process. The International Association for Impact Assessment (IAIA) and
+the Institute of Environmental Management and Assessment (IEMA) have
+drawn on these to prepare a statement of <a title="EIA Best Practice Principles" target="_blank" href="http://eia.unu.edu/wiki/index.php/EIA_Best_Practice">EIA Best Practice</a> (see EIA Wiki) for reference and use by their members <span style="background-color: rgb(255, 0, 0);"></span>. The Effectiveness Study identified three core values on which the EIA process is based:
+</p>
+<ul>
+<li>integrity– the EIA process should meet internationally accepted requirements and standards of practice;
+ </li>
+<li>utility– the EIA process should provide the information which is sufficient and relevant for decision-making; and
+ </li>
+<li>sustainability– the EIA process should result in the
+implementation of environmental safeguards which are sufficient to
+mitigate serious adverse effects and avoid irreversible loss of resource
+ and ecosystem functions.
+ </li>
+</ul>
+<p>Basic or guiding principles of EIA good practice are listed in the
+table below. These are applicable to all types of proposals and by all
+EIA systems. When applying or referring to them, it is important to
+consider the principles as a single package, recognising their varying
+interrelationships. For example, some principles overlap (e.g.,
+transparent and participative); others may be counteracting if
+considered without reference to the broader framework (e.g. rigour and
+efficiency). The principles should be applied as part of a systematic
+and balanced approach, having regard to the context and circumstances.
+</p>
+<table>
+<caption><b>Guiding principles of EIA good practice</b></caption>
+<thead>
+<tr><th style="width: 10%;"><b>Principles</b>
+ </th>
+<th style="width: 90%;"><b>Practical application</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i>Source: Sadler, 1996; IAIA and IEMA, 1999. </i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>Purposive
+ </td>
+<td>EIA should meet its aims of informing decision making and ensuring
+an appropriate level of environmental protection and human health.
+ </td>
+</tr>
+<tr>
+<td>Focused
+ </td>
+<td>EIA should concentrate on significant environmental effects, taking into account the issues that matter.
+ </td>
+</tr>
+<tr>
+<td>Adaptive
+ </td>
+<td>EIA should be adjusted to the realities, issues and circumstances of the proposals under review.
+ </td>
+</tr>
+<tr>
+<td>Participative
+ </td>
+<td>EIA should provide appropriate opportunities to inform and involve
+the interested and affected publics, and their inputs and concerns
+should be addressed explicitly.
+ </td>
+</tr>
+<tr>
+<td>Transparent
+ </td>
+<td>EIA should be a clear, easily understood and open process, with
+early notification procedure, access to documentation, and a public
+record of decisions taken and reasons for them.
+ </td>
+</tr>
+<tr>
+<td>Rigorous
+ </td>
+<td>EIA should apply the ‘best practicable’ methodologies to address the impacts and issues being investigated.
+ </td>
+</tr>
+<tr>
+<td>Practical
+ </td>
+<td>EIA should identify measures for impact mitigation that work and can be implemented.
+ </td>
+</tr>
+<tr>
+<td>Credible
+ </td>
+<td>EIA should be carried out with professionalism, rigor, fairness, objectivity, impartiality and balance.
+ </td>
+</tr>
+<tr>
+<td>Efficient
+ </td>
+<td>EIA should impose the minimum cost burden on proponents consistent with meeting process requirements and objectives.
+ </td>
+</tr>
+</tbody>
+</table>
+<p>Operating principles describe how the basic principles of EIA good practice should be implemented. The <a title="EIA Operating Principles" target="_blank" href="http://eia.unu.edu/wiki/index.php/EIA_Operating_Principles">EIA Operating Principles</a>
+ (see EIA Wiki) provide initial guidance on how to undertake EIA and
+what results practitioners should aim to deliver. When applying these
+operating principles, reference should be made to the framework of EIA
+legislation, procedure and guidance that is in force in a country or
+jurisdiction. In certain countries, the relatively early stage of EIA
+process development or limited resources may constrain the application
+of some of the operating principles. </p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:00 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=100#comments" title="Comment on 1-4 Principles of EIA administration and practice">Comments (1)</a> </div>
+
+</div>
+
+
+<h2 id="comments">1 Comment
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-63135">
+ <p>First of all I would like to thank very much for the web for giving
+us this opportunity, which is very great resource specially for
+developed and developing countries, like Albania and as a specialist I
+have almost a few years that I have based as an special experience on my
+ lectures, inside and outside my country! Thank you again!</p>
+ <p><cite>Comment by Prof. Dr. Bashkim Lushaj — April 17, 2012 @ <a href="#comment-63135">1:25 am</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=100"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="100" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-4%20Principles%20of%20EIA%20administration%20and%20practice_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'100'});
+var load_cmc = function(){linktracker_init(3787197,100,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript.html
new file mode 100644
index 0000000..af463b4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_Vus4FHE-i6O0Z5rMwdH50uZHZGDwZ8zIKED6mDQmsNRVtZLC42Ak6PcR0-PCvmkoe7VCyoiDbwTQ4caDjBjBAT0CCn5K0ngYlY_5BXFUkx9pLBoU8QTH9bSsX8HimyfuaVlXQWf2rV2iKjAD9sk7JwLaX0s7Zv5FYX2axZXWyUVpxIrv1JU" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_Vus4FHE-i6O0Z5rMwdH50uZHZGDwZ8zIKED6mDQmsNRVtZLC42Ak6PcR0-PCvmkoe7VCyoiDbwTQ4caDjBjBAT0CCn5K0ngYlY_5BXFUkx9pLBoU8QTH9bSsX8HimyfuaVlXQWf2rV2iKjAD9sk7JwLaX0s7Zv5FYX2axZXWyUVpxIrv1JU&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript_data/image.jpg
new file mode 100644
index 0000000..2c137e3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-4 Principles of EIA administration and practice_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process.html
new file mode 100644
index 0000000..0fe0b56
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process.html
@@ -0,0 +1,664 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=101">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 322px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101 current_page_item"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-101">
+ <h1 class="storytitle">1-5 Key elements of the EIA process <a href="http://eia.unu.edu/course/?page_id=101" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>EIA systems can be described by reference to three components:
+</p>
+<ol>
+<li>the legal and institutional framework of regulation, guidance and
+procedure, which establishes the requirements for the conduct of EIA;
+ </li>
+<li>the steps and activities of the EIA process, as applied to specific types of proposals; and
+ </li>
+<li>the practice and performance of EIA, as evidenced by the quality of
+EIA reports prepared, the decisions taken and the environmental benefits
+ delivered.
+ </li>
+</ol>
+<p><font size="3"><b>Legal and institutional framework</b></font>
+</p>
+<p>The provision for EIA may be made through legislation, administrative
+ order or policy directive. Many countries have now enacted some type of
+ EIA legislation, which generally can be classified into either a
+comprehensive or enabling statute. Clear and specific legal provision is
+ internationally accepted as the most appropriate basis for EIA. In many
+ cases, regulations (mandatory rules) and procedural guidance (advisory
+interpretation) elaborate how EIA legislation is to be implemented.
+Further information of these arrangements can be found in Section 2 –
+Law, policy and institutional arrangements. In this Section, note is
+made only of the main features of the EIA legal and institutional
+frameworks. These also comprise points of reference for developing or
+strengthening an EIA system:
+</p>
+<p><font size="2"><b>Basic responsibilities</b></font>
+</p>
+<p>The proponent normally carries out the EIA in accordance with
+directions given by the competent authority (usually the agency which
+makes the final decision on the proposal but in certain cases an
+independent commission or panel). An environment agency (or in some
+cases a specialised EIA body) oversees the process and reviews the study
+ with inputs from other government departments. Usually, EIA studies are
+ carried out by an interdisciplinary team, which is appointed
+specifically to the task and has an appropriate range of scientific,
+economic and social expertise.
+</p>
+<p><font size="2"><b>Scope of application</b></font>
+</p>
+<p>Some EIA systems are relatively narrow in coverage; e.g. limited to
+projects of a specified type and size. Others have a broader remit, for
+example encompassing all proposals that have potentially significant
+adverse environmental impacts. In addition, the environment is defined
+broadly; for example to include social, health and cumulative effects.
+The inclusion of these broader aspects of EIA are now accepted as the
+international standard of good practice and their coverage should be
+mandatory.
+</p>
+<p><font size="2"><b>Consideration of alternatives</b></font>
+</p>
+<p>Consideration of alternatives is mandatory in some EIA systems but
+discretionary in others. Varied provision is made for including a range
+of alternatives to a proposal, and there are different requirements for
+the evaluation and comparison of alternatives as part of the EIA
+process. At a minimum, explicit provision should be made for the
+consideration of the main or ‘reasonable’ alternatives to a proposal
+ (including no action). This component is a critical determinant of
+effective EIA.
+</p>
+<p><font size="2"><b>Public involvement</b></font>
+</p>
+<p>This is a cornerstone of EIA and most systems include provision for
+public involvement. However, there are marked differences in specific
+requirements; e.g. regarding access to information, procedures for
+notification and involvement of the public, the stage of the EIA process
+ at which these are applied and third party rights of appeal. At a
+minimum, public involvement should take account of the concerns of those
+ directly affected by a proposal.
+</p>
+<p><font size="2"><b>Quality control and assurance</b></font>
+</p>
+<p>Within EIA systems, the components described above provide a set of
+legal and institutional controls on the quality and effectiveness of the
+ process. In addition, the main stages of the EIA process itself
+constitute a further set of procedural checks and balances. The
+respective functions of each stage are described below; however, they
+should be applied iteratively as part of a ‘whole process’ approach
+to provide EIA quality assurance.
+</p>
+<p> <a href="http://eia.unu.edu/course/images/Generalised_EIA.pdf"><br>
+<img alt="" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/Generalised-EIA.gif" hspace="0" vspace="0" border="0" align="right"> </a></p>
+<p><font size="3"><b>EIA process</b></font>
+</p>
+<p>The particular components, stages and activities of an EIA process
+will depend upon the requirements of the country or donor. However, most
+ EIA processes have a common structure (see flow chart below and watch
+the video) and the application of the main stages is a basic standard of
+ good practice. Typically, the EIA process begins with screening to
+ensure time and resources are directed at the proposals that matter
+environmentally. It should end with some form of follow up on the
+implementation of the decisions and actions taken as a result of an EIA
+report.
+</p>
+<p>(click on the EIA Process Flowchart at the right)
+</p>
+<p><font size="3"><b>EIA practice and outcomes</b></font>
+</p>
+<p>Marked variations occur in the quality of EIA practice and outcomes
+among countries, reflecting the legal provisions, institutional
+arrangements and procedures that are in force in different
+jurisdictions. In addition, the quality of EIA practice varies on a
+case-by-case basis within the same system, depending upon events, the
+complexity of the proposal, the experience of those involved and the
+time and money allocated. Strengths and weaknesses of EIA practice are
+well documented in the literature, generally and with reference to the
+experience of certain countries and types of projects.
+</p>
+<div class="flvPlayer"> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" height="260" width="320"><param name="movie" value="http://eia.unu.edu/flvplayer.swf?file=http://eia.unu.edu/course/animation/01a_the_eia_process.flv&amp;autoStart=false;"><param name="quality" value="high"><param name="wmode" value="transparent"><embed src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/flvplayer.swf" quality="high" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="260" width="320"><br>
+ </object></div>
+<p></p>
+<p>Widely recognised deficiencies of EIA practice include:
+</p>
+<ul>
+<li>Technical shortcomings, expressed by the poor quality of many EIA
+reports. The accuracy of impact predictions, the utility of mitigation
+and management measures, and the relevance of reports for
+decision-making often fall short of internationally accepted standards.
+ </li>
+<li>Procedural limitations, including inconsistencies in process
+administration and guidance. Time delays and costs of applying EA remain
+ a serious concern for project proponents. Affected communities are more
+ concerned with the lack of quality control of EIA studies or
+enforcement of mitigation measures.
+ </li>
+<li>Structural issues, stemming from the application of EIA as a
+separate process, unrelated to the project cycle or the larger context
+of decisionmaking.
+ </li>
+<li>In order to be effective, EIA requires a coherent policy-planning
+framework and systematic follow up procedures. Often neither area is
+well established.
+ </li>
+</ul>
+<p>A number of studies have drawn attention to the particular
+constraints on EIA practice in developing countries as compared to
+developed ones. However, most developing countries have some experience
+in EIA and some have a considerable track record, predating the
+introduction of the EIA Directive in Europe. There are particular
+limitations on domestic EIA practice in poorer countries, where
+typically institutional arrangements are weak, and human, technical and
+financial resources are lacking. In these circumstances, the development
+ banks and international aid agencies play a major role, both long-term
+through capacity building for the environment and immediately through
+their own EIA requirements.
+</p>
+<p>What constitute good outcomes for EIA practice? Where international
+standards apply or can be approximated, the following targets should be
+within the reach of EIA practice:
+</p>
+<ul>
+<li>screens out environmentally unsound projects;
+ </li>
+<li>modifies the design of feasible proposals to reduce their environmental impact;
+ </li>
+<li>identifies the best practicable environmental option;
+ </li>
+<li>predicts the significant adverse effects of proposals with reasonable accuracy;
+ </li>
+<li>identifies mitigation measures that work successfully to avoid, reduce and offset major impacts;
+ </li>
+<li>influences decision making and approvals and the implementation of terms and conditions; and
+ </li>
+<li>results in environmental gains and benefits relative to other options.
+ </li>
+</ul>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — brendan @ 12:05 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=101#comments" title="Comment on 1-5 Key elements of the EIA process">Comments (14)</a> </div>
+
+</div>
+
+
+<h2 id="comments">14 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-4243">
+ <p>This is such a very helpful sight for non-technical persons like me
+who are in environmental work. The video clip enabled me to easily
+understand the eia process.</p>
+ <p><cite>Comment by <a href="http://tanggol.org/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/tanggol.org');" rel="external nofollow" class="url">vida gonzales</a> — February 26, 2008 @ <a href="#comment-4243">4:56 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-4521">
+ <p>I really got interest on this course module specially the videos are very explanatory and i like the way you present it<br>
+ thank you very much. I am doing my masters study in hydro power
+development in NTNU. I was reading for exam in environmental impacts of
+hydro power and I found the website to be very helpful. Thank you.</p>
+ <p><cite>Comment by YONAS — March 12, 2008 @ <a href="#comment-4521">7:27 am</a></cite> </p>
+ </li>
+
+ <li id="comment-5098">
+ <p>I would like to cite some of this work…how do I cite it?</p>
+ <p><cite>Comment by Louise du Preez — April 11, 2008 @ <a href="#comment-5098">10:20 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-5177">
+ <p>United Nations University (2007) Open Educational Resource on
+Environmental Impact Assessment, based on the UNEP EIA Training Manual,
+access at <a href="http://eia.unu.edu/" rel="nofollow">http://eia.unu.edu</a></p>
+ <p><cite>Comment by brendan — April 14, 2008 @ <a href="#comment-5177">9:50 am</a></cite> </p>
+ </li>
+
+ <li id="comment-29809">
+ <p>I as unable to view the video on EIA process and would like the video to be emailed to me please.<br>
+Thanks</p>
+ <p><cite>Comment by Susan — March 6, 2009 @ <a href="#comment-29809">3:18 am</a></cite> </p>
+ </li>
+
+ <li id="comment-32620">
+ <p>Excellent…the language, the graphics, the pace. Very friendly. This
+makes studying and preparing for exams so much easier and enjoyable.</p>
+ <p><cite>Comment by Andrea — July 5, 2009 @ <a href="#comment-32620">2:03 am</a></cite> </p>
+ </li>
+
+ <li id="comment-35559">
+ <p>This has been very useful in my understanding the process of
+EIA.Relevant in my exam preperation.Am doing a module -Environmental
+management in which EIA was treated for my MSC course in Industrial
+Environmental Management. Thanks.</p>
+ <p><cite>Comment by BUKOLA BROWN — December 12, 2009 @ <a href="#comment-35559">10:34 am</a></cite> </p>
+ </li>
+
+ <li id="comment-46690">
+ <p>Thank you for having this web site in the internate.<br>
+I am Msc. student in Environmental Science at Addis Ababa University. I
+am interested to have your course module, because its acadamic
+usefulness is unquestioable. Would you send it to me,please?<br>
+I appreciate your hard work.</p>
+ <p><cite>Comment by GETENET GEDLU — November 17, 2010 @ <a href="#comment-46690">2:03 am</a></cite> </p>
+ </li>
+
+ <li id="comment-55774">
+ <p>I as unable to view the video on EIA process and would like the video to be emailed to me please.<br>
+ Thanks</p>
+ <p><cite>Comment by Doyin — July 9, 2011 @ <a href="#comment-55774">8:03 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-58754">
+ <p>This sight has really helped me by providing important information about EIA. Keep it up for the good work.</p>
+ <p><cite>Comment by Mark Mkutano — October 7, 2011 @ <a href="#comment-58754">7:06 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-61386">
+ <p>Helped me a lot in my revision for my EIA Exam. Currently a 3rd Year
+ student reading for a B.A. (Hons.) Geography at the University of
+Malta.</p>
+<p>Thanks :)</p>
+ <p><cite>Comment by Darren — January 30, 2012 @ <a href="#comment-61386">9:24 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-63341">
+ <p>This has been very useful in my understanding the process of EIA</p>
+ <p><cite>Comment by <a href="http://google/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/google');" rel="external nofollow" class="url">irshad khan</a> — April 26, 2012 @ <a href="#comment-63341">4:41 am</a></cite> </p>
+ </li>
+
+ <li id="comment-106585">
+ <p>I love this course. Can you please email me the video? The processes are so easy to remember when we look at the video.</p>
+ <p><cite>Comment by Jennie — January 9, 2013 @ <a href="#comment-106585">3:47 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-106665">
+ <p>Thank you for the team for this wonderful work. I’ve read all the
+chapters and the activities were effective. I’ve downloaded the video
+and information from your files too. Cheers.</p>
+ <p><cite>Comment by Jennie — January 10, 2013 @ <a href="#comment-106665">12:28 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=101"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="101" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-5%20Key%20elements%20of%20the%20EIA%20process_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'101'});
+var load_cmc = function(){linktracker_init(3787197,101,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Generalised-EIA.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Generalised-EIA.gif
new file mode 100644
index 0000000..63d38a9
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Generalised-EIA.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/flvplayer.swf b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/flvplayer.swf
new file mode 100644
index 0000000..c230d33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/flvplayer.swf
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript.html
new file mode 100644
index 0000000..cdf7c30
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuuXBq2-Mev01m-H0nJM-6HlzDYp7ONLxv8W3wAzA8pNlG8Ny5KKtr43Hdh3VYtD-i6kelMVK2UTrUDoAW6SC024dR7gRyRlrqufGFIl7-sMvIqT61sxMpRppyv1RikK0owDxyywWFIejTgB7qcv78wdGo2jhZYOmXvj31LZUYzo1OJa-BY" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuuXBq2-Mev01m-H0nJM-6HlzDYp7ONLxv8W3wAzA8pNlG8Ny5KKtr43Hdh3VYtD-i6kelMVK2UTrUDoAW6SC024dR7gRyRlrqufGFIl7-sMvIqT61sxMpRppyv1RikK0owDxyywWFIejTgB7qcv78wdGo2jhZYOmXvj31LZUYzo1OJa-BY&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript_data/image.jpg
new file mode 100644
index 0000000..c3e2aa3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-5 Key elements of the EIA process_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA.html
new file mode 100644
index 0000000..a09d121
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA.html
@@ -0,0 +1,596 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=102">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 310px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102 current_page_item"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-102">
+ <h1 class="storytitle">1-6 Costs and benefits of EIA <a href="http://eia.unu.edu/course/?page_id=102" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>Although there are costs associated with undertaking EIA,
+experience has shown that the potential savings over the life of a
+project can repay the investment many times over. The savings can be
+economic (e.g. identification of least cost alternative) as well as
+environmental (e.g. impact reduction, maintaining other resource use
+opportunities). Generally the earlier EIA process is introduced in the
+project cycle, the greater the potential returns. When EIA is integrated
+ into the project preparation phase, environmental design considerations
+ can be introduced in the first place rather than the proposal having to
+ be modified later.
+</p>
+<p><font size="2"><b>Benefits</b></font>
+</p>
+<p>The benefits of EIA can be direct, such as the improved design or
+location of a project, or indirect, such as better quality EIA work or
+raised environmental awareness of the personnel involved in the project.
+ In these cases, there will be with flow-on effects in their future
+work. As mentioned above, these potential gains from EIA increase the
+earlier the process is applied in the design process.
+</p>
+<p>In general the benefits of EIA include:
+</p>
+<ul>
+<li>Better environmental planning and design of a proposal. Carrying out
+ an EIA entails an analysis of alternatives in the design and location
+of projects. This can result in the selection of an improved technology,
+ which lowers waste outputs or an environmentally optimum location for a
+ project. A well-designed project can minimise risks and impacts on the
+environment and people, and thereby avoid associated costs of remedial
+treatment or compensation for damage.
+ </li>
+<li>Ensuring compliance with environmental standards. Compliance with
+environmental standards reduces damage to the environment and disruption
+ to communities. It also avoids the likelihood of penalties, fines and
+loss of trust and credibility.
+ </li>
+<li>Savings in capital and operating costs. EIA can avoid the undue
+costs of unanticipated impacts. These can escalate if environmental
+problems have not been considered from the start of proposal design and
+require rectification later. An ‘anticipate and avoid’ approach is
+much cheaper than ‘react and cure’. Generally, changes which must be
+ made late in the project cycle are the most expensive.
+ </li>
+<li>Reduced time and costs of approvals of development applications. If
+all environmental concerns have been taken into account properly before
+submission for project approval, then it is unlikely that delays will
+occur as a result of decision-makers asking for additional information
+or alterations to mitigation measures. Increased project acceptance by
+the public.
+ </li>
+</ul>
+<p>This is achieved by an open and transparent EIA process, with
+provision of opportunities for public involvement of people who are most
+ directly affected by and interested in the proposal, in an appropriate
+way that suits their needs.
+</p>
+<div class="flvPlayer"> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" height="260" width="320"><param name="movie" value="http://eia.unu.edu/flvplayer.swf?file=http://eia.unu.edu/course/video/1a_costs_and_benifits.flv&amp;autoStart=false;"><param name="quality" value="high"><param name="wmode" value="transparent"><embed src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/flvplayer.swf" quality="high" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="260" width="320"><br>
+ </object></div>
+<p></p>
+<p><font size="2"><b>Costs</b></font>
+</p>
+<p>It can be difficult to determine the exact costs of an EIA because
+major projects typically require a large number of investigations and
+reports, often for closely related purposes (e.g. engineering
+feasibility studies of hydrology and surface materials). The World Bank
+notes that the cost of preparing an EIA rarely exceeds one per cent of
+the project costs and this percentage can be reduced further if local
+personnel are used to do most of the work. For Bank projects, the
+relative cost of an EIA typically ranges from only 0.06 per cent to 0.10
+ per cent of total project costs. The total cost of an EIA might range
+from a few thousand dollars for a very small project, to over a million
+dollars for a large and complex project, which has a significant
+environmental impact and requires extensive data collection and
+analysis.
+</p>
+<p>Although many proponents complain that EIA causes excessive delays in
+ projects, many of these are caused by poor administration of the
+process rather than by the process itself. These occur when:
+</p>
+<ul>
+<li>the EIA is commenced too late in the project cycle;
+ </li>
+<li>the terms of reference are poorly drafted;.
+ </li>
+<li>the EIA is not managed to a schedule;
+ </li>
+<li>the technical and consultative components of EIA are inadequate; and
+ </li>
+<li>the EIA report is incomplete or deficient as a basis for decision making.
+ </li>
+</ul>
+<p>Similar considerations apply to the timeframe for the EIA process.
+Most projects merely require screening and might take only an hour or
+two of work. Where further EIA work is necessary, the time taken can
+range from a few days or weeks, for a small irrigation or a minor
+infrastructure project, to two years or more for a large dam or a major
+infrastructure project. Generally speaking, the costs and time involved
+in EIA should decrease as experience is gained with the process and
+there is a better understanding of the impacts associated with different
+ types of projects and the use of appropriate methods. Over a longer
+timeframe, the availability of baseline data should also increase.
+</p>
+<p>All participants in the EIA process are ‘stakeholders’, who
+pursue particular interests and hold different views and preferences.
+Full public involvement, open to all affected and interested parties,
+provides the best means of ensuring the EIA process is fair and
+credible. It allows decision-makers and participants themselves to gain
+an understanding of the diversity and balance of opinion on the issues
+at stake. The final decision can then be made in a fully informed and
+transparent manner, having regard to all the facts and the views by
+stakeholders and the public at large Section 3 – Public involvement).
+</p>
+<p>In addition, there are a number of specific measures that can help to
+ make the EIA process transparent, accessible and accountable to the
+public. Examples of measures that reinforce the fairness of the process
+include:
+</p>
+<ul>
+<li>requiring the proponent to register all consultants, their expertise and responsibilities with the administering agency;
+ </li>
+<li>publishing these details in the terms of reference and the EIA report;
+ </li>
+<li>making all EIA documents and reports available to the public; and
+ </li>
+<li>publishing reasons for decisions – screening and final approvals
+– together with requirements and terms and conditions for mitigation
+and environmental management plans.
+ </li>
+</ul>
+<p>Capacity building is the long-term, voluntary process of increasing
+the ability of a country to identify and solve its own problems and
+risks, and to maximise its opportunities.
+</p>
+<p>In this context, countries should firstly aim to carry out their own
+EIAs of proposals. Second, they should aim to use local experts as much
+as possible when undertaking EIAs of proposals financed by the World
+Bank and other multilateral lending agencies. Where this is not possible
+ without compromising the quality of EIAs and outside experts must be
+engaged, every opportunity should be taken to transfer their expertise
+to local personnel. This strategy will make the implementation of EIA
+recommendations more effective and strengthen the basis of EIA expertise
+ locally.
+</p>
+<p>Capacity building can be carried out in a number of ways, including
+institutional strengthening, technical assistance and advice, and EIA
+training programmes. A systematic, long-term commitment will be
+necessary to overcome limited capacity of many developing countries to
+undertake EIA. In addition, this process should be backed by activities
+to strengthen education and research institutions. EIA-specific training
+ can be done at many different levels and over different periods to meet
+ a variety of needs.
+</p>
+<p>A systematic EIA capacity building programme will need to provide a
+range of different activities. These could include advice on drafting or
+ strengthening EIA legislation and procedures, improving their
+application to relevant sectors, such as energy and mining, and
+strengthening particular aspects of practice, such as public
+involvement. Pilot projects involving local experts in actual EIAs of
+proposals can be used to transfer ‘hands on’ knowledge and skills.
+Supporting activities include developing resource materials and
+establishing a network of practitioners with experience in EIA or
+technical analysis.
+</p>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:10 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=102#comments" title="Comment on 1-6 Costs and benefits of EIA">Comments (5)</a> </div>
+
+</div>
+
+
+<h2 id="comments">5 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-655">
+ <p>I have found this very useful in revising for my EIA exam here at the University of Birmingham, England. Thank you</p>
+ <p><cite>Comment by <a href="http://www.westbromblog.blogspot.com/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/www.westbromblog.blogspot.com');" rel="external nofollow" class="url">pete</a> — June 1, 2007 @ <a href="#comment-655">5:26 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-59773">
+ <p>Great stuff, helped me in preparing for my exam at USP in Fiji.</p>
+ <p><cite>Comment by <a href="http://www.spc.int/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/www.spc.int');" rel="external nofollow" class="url">Vinesh Prasad</a> — November 17, 2011 @ <a href="#comment-59773">8:44 am</a></cite> </p>
+ </li>
+
+ <li id="comment-97131">
+ <p>I would like to take this course, what should i do?<br>
+Is there any scholarship available for this course?<br>
+I personally interest on EIA implementation since I was a student at Faculty Environmental Science, National University of Laos.</p>
+ <p><cite>Comment by Toulie — November 12, 2012 @ <a href="#comment-97131">9:19 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-106845">
+ <p>I wish I had stumbled on this website earlier instead of the day before my EIA finals.</p>
+ <p><cite>Comment by Andrew — January 11, 2013 @ <a href="#comment-106845">12:25 am</a></cite> </p>
+ </li>
+
+ <li id="comment-108629">
+ <p>Cool stuff, finally i can face my exams with confidence in an hours time. Thanks<br>
+University of Nairobi, Kenya</p>
+ <p><cite>Comment by Steve Ouma — January 23, 2013 @ <a href="#comment-108629">8:00 am</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=102"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="102" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-6%20Costs%20and%20benefits%20of%20EIA_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'102'});
+var load_cmc = function(){linktracker_init(3787197,102,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/flvplayer.swf b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/flvplayer.swf
new file mode 100644
index 0000000..c230d33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/flvplayer.swf
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript.html
new file mode 100644
index 0000000..442e7c4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VutDWOlDMRTwkbftCM4f5F6KkXVIKwmGoDUlgXt5nsrV7p7qhEDXem5kx630RYAb9rtNB8lMBw1tX4kzzh4j2T1p92doZvO9YiWT7V3dUH-8KQQiMhGMByfOgUnDpZMIP9SswJvjtIerLcrK0hU3WOiFPbq14XcHn9D-xykz8FZas21MsrA" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VutDWOlDMRTwkbftCM4f5F6KkXVIKwmGoDUlgXt5nsrV7p7qhEDXem5kx630RYAb9rtNB8lMBw1tX4kzzh4j2T1p92doZvO9YiWT7V3dUH-8KQQiMhGMByfOgUnDpZMIP9SswJvjtIerLcrK0hU3WOiFPbq14XcHn9D-xykz8FZas21MsrA&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript_data/image.jpg
new file mode 100644
index 0000000..23fe6e3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-6 Costs and benefits of EIA_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary.html
new file mode 100644
index 0000000..a43a0f9
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary.html
@@ -0,0 +1,460 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 1-7 Summary</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 1-7 Summary Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=175">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="1. Background" href="http://eia.unu.edu/course/?page_id=25">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 310px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175 current_page_item"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-175">
+ <h1 class="storytitle">1-7 Summary <a href="http://eia.unu.edu/course/?page_id=175" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>EIA involves using a systematic process to evaluate the
+environmental impacts of a proposed development or action. As
+demonstrated in this Section, EIA has a well-established history and
+international standing. Public participation is essential in good
+practice EIA, and there are both costs and benefits associated with
+implementation. Principles and practice of EIA administration and
+technical processes are introduced and these will be examined in more
+detail in subsequent Sections of the Module.
+</p>
+<p>You have now completed Section 1 of 11 in this Module, Environmental
+Impact Assessment. To demonstrate the learning outcomes of this Section,
+ check that you are now able to:
+</p>
+<ul>
+<li>Demonstrate an introductory understanding of EIA and why it is necessary;
+ </li>
+<li>Appreciate the worldwide influence of EIA practice.
+ </li>
+</ul>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">January 30, 2007 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 6:06 am </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=175#comments" title="Comment on 1-7 Summary">Comments (4)</a> </div>
+
+</div>
+
+
+<h2 id="comments">4 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-41409">
+ <p>I am so happy I found this site! I have been working on
+environmental teams for several years and performing informal
+assessments. My new position is going to require form EIA and on a
+global scale.</p>
+<p>My only suggestion would be to include more practice
+quizzes/activities. There is so much material provided, it could help
+reinforce what we have learned. Thanks so much, as I am sure putting
+this together was not an easy task.</p>
+ <p><cite>Comment by Grace — June 3, 2010 @ <a href="#comment-41409">10:14 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-46474">
+ <p>This site provides a good information about EIA, it helps individual
+ especially the students to learn and become aware of the importance of
+EIA to the society. The video is also very helpful, gives us deeper
+insight. It would be more appreciated if more activities or online
+quizzes is included to gauge ourselves on what we have learned…for
+practice purposes. Thanks for this site!</p>
+ <p><cite>Comment by Gina Step — November 10, 2010 @ <a href="#comment-46474">8:14 am</a></cite> </p>
+ </li>
+
+ <li id="comment-55758">
+ <p>It’s a good nice website.I got lot of knowledge through this.As an
+environmental engineer I can do more efficiently in my work by applying
+this knowledge.<br>
+Thanks</p>
+ <p><cite>Comment by E.subrahmanyam — July 9, 2011 @ <a href="#comment-55758">2:52 am</a></cite> </p>
+ </li>
+
+ <li id="comment-59060">
+ <p>As a Civil Engineer, I have found this site very valuable to my work. Many thanks for this effort!</p>
+ <p><cite>Comment by Dr. Stephen Nyende-Byakika — October 19, 2011 @ <a href="#comment-59060">1:34 am</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=175"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+ <a href="http://eia.unu.edu/course/wp-trackback.php?p=175" rel="trackback">TrackBack <abbr title="Uniform Resource Identifier">URI</abbr></a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="175" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%201-7%20Summary_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'175'});
+var load_cmc = function(){linktracker_init(3787197,175,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript.html
new file mode 100644
index 0000000..6b23866
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VusfGiRUDUA2GKoeJP3bQOqeB3DznJBKCa6i-BSCQp5LEa-AyOzGZHok2Mssx-Fq1cUXYd-rskkJrKeRUIBhIYutBW-z-83mVeDixnU0l5PZ1x_5rQ-Zlr61aMdBslevwM_ZwcLcY8cK2CGrYFTKId86s8m4qpcJBMNuxpszj3SG35mhWLo" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VusfGiRUDUA2GKoeJP3bQOqeB3DznJBKCa6i-BSCQp5LEa-AyOzGZHok2Mssx-Fq1cUXYd-rskkJrKeRUIBhIYutBW-z-83mVeDixnU0l5PZ1x_5rQ-Zlr61aMdBslevwM_ZwcLcY8cK2CGrYFTKId86s8m4qpcJBMNuxpszj3SG35mhWLo&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript_data/image.jpg
new file mode 100644
index 0000000..ecd5d00
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 1-7 Summary_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction.html
new file mode 100644
index 0000000..22afb34
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction.html
@@ -0,0 +1,422 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-1 Introduction</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-1 Introduction Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=146">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 285px;">
+ <li class="page_item page-item-146 current_page_item"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-146">
+ <h1 class="storytitle">2-1 Introduction <a href="http://eia.unu.edu/course/?page_id=146" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>This topic provides insight into the different types of EIA
+systems, the range of legal, policy and institutional arrangements that
+can be provided and the directions in which these are developing. It
+also examines the factors that need to be considered when establishing
+or modifying a national EIA system.
+</p>
+<p><font size="3"><b>Learning Outcomes of this Section</b></font>
+</p>
+<p>On successful completion of this Section, you will be able to:
+</p>
+<ul>
+<li>Understand the purpose, scope and content of EIA policy and legislation
+ </li>
+<li>Understand the EIA requirements of International Organisations and relevant International Environmental Agreements
+ </li>
+<li>Demonstrate understanding of the legal principles underpinning a functional EIA system
+ </li>
+<li>Show familiarity with duties placed on local authorities and developers
+ </li>
+</ul>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">August 1, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — brendan @ 2:25 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=146#respond" title="Comment on 2-1 Introduction">Comments (0)</a> </div>
+
+</div>
+
+
+<h2 id="comments">No Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+ <p>No comments yet.</p>
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=146"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+ <a href="http://eia.unu.edu/course/wp-trackback.php?p=146" rel="trackback">TrackBack <abbr title="Uniform Resource Identifier">URI</abbr></a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="146" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-1%20Introduction_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'146'});
+var load_cmc = function(){linktracker_init(3787197,146,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript.html
new file mode 100644
index 0000000..22915a6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuspiJGr5acUHcvq1DKsd4DQb2FrJC6cZQnQ6raX783ZYuaqcipSP2IoKydZm5uHupndnO-FBhASh0L_gxGj_2Z-UOwMeKH3C1TDb1UZ1arOKwGbpcmEro3c9SNmMGllDHo5OKPlyIDee67Er7QO-Mqasb2rm29DwKV650vewNdW9XoSO0o" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuspiJGr5acUHcvq1DKsd4DQb2FrJC6cZQnQ6raX783ZYuaqcipSP2IoKydZm5uHupndnO-FBhASh0L_gxGj_2Z-UOwMeKH3C1TDb1UZ1arOKwGbpcmEro3c9SNmMGllDHo5OKPlyIDee67Er7QO-Mqasb2rm29DwKV650vewNdW9XoSO0o&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript_data/image.jpg
new file mode 100644
index 0000000..3ee4331
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-1 Introduction_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems.html
new file mode 100644
index 0000000..243845c
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems.html
@@ -0,0 +1,711 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-2 About EIA Systems</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-2 About EIA Systems Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=109">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 285px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109 current_page_item"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-109">
+ <h1 class="storytitle">2-2 About EIA Systems <a href="http://eia.unu.edu/course/?page_id=109" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>EIA is an evolving process. When establishing or strengthening an
+EIA system, there is an opportunity to build upon the experience of
+others and to move towards legal and policy frameworks that support
+environmental sustainability.
+</p>
+<p>EIA systems have become progressively more broadly based,
+encompassing a wider range of impacts, higher levels of decision-making
+and new areas of emphasis (as described in Section 1 – Introduction
+and overview of EIA). In particular, there are trends toward:
+</p>
+<ul>
+<li>more systematic procedures for EIA implementation, quality control, compliance and enforcement;
+ </li>
+<li>integrated consideration of biophysical, social, risk, health and other impacts;
+ </li>
+<li>extended temporal and spatial frameworks, which include cumulative,
+trans-boundary and ecosystem-level effects and, to a lesser extent,
+global change;
+ </li>
+<li>increasing provision for strategic environmental assessment (SEA) of policy, plan and programme proposals;
+ </li>
+<li>incorporation of sustainability perspectives and principles into EIA and SEA processes; and
+ </li>
+<li>greater linkage of EIA systems with other planning, regulatory and management regimes.
+ </li>
+</ul>
+<p>These trends are identified in the International Study of EA
+Effectiveness. This study also illustrates how EIA has become
+institutionalised and looks at the strengths and weaknesses of current
+practice in relation to different legal policy and institutional
+arrangements. Other recent and relevant sources of information include
+the <i>Handbook of Environmental Impact Assessment</i> and the <i>Environmental Assessment Sourcebook Updates</i> issued by the World Bank (see references).
+</p>
+<p>Many lessons can be drawn from these materials by those who are
+responsible for introducing or modifying EIA systems, or are amending
+particular legal, policy and institutional arrangements to international
+ standards. Not all aspects may be appropriate or replicable in certain
+developing countries without further EIA capacity development. However,
+there is a general trend toward strengthening the foundations and key
+features of EIA systems in both developed and developing countries. Key
+institutional milestones are summarised in the table below.
+</p>
+<table>
+<caption><b>Key international developments in EIA law, policy and institutional arrangements – the last decade</b></caption>
+<thead>
+<tr><th style="width: 40%;"><b>Key Instrument/Event</b>
+ </th>
+<th style="width: 60%;"><b>Requirements/Outcome</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i>Updated and amended from Sadler, 1996</i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td><b>Rio Declaration on Environment and Development</b>
+ </td>
+<td>Calls for use of EIA as an instrument of national decision-making
+(Principle 17); other principles also relevant to EIA practice (e.g.
+Principle 15 on the application of the precautionary approach).
+ </td>
+</tr>
+<tr>
+<td><b>UN Conventions on Climate Change and Biological Diversity (1992)</b>
+ </td>
+<td>Cite EIA as an implementing mechanism (Articles 4 and 14 respectively refer)
+ </td>
+</tr>
+<tr>
+<td><b>Comprehensive reform of long-established EIA systems</b>
+ </td>
+<td>e.g. New Zealand (1991), Canada (1995), Australia (1999).
+ </td>
+</tr>
+<tr>
+<td><b>New or revised EIA legislation enacted by many developing and transitional countries</b>
+ </td>
+<td>e.g. Vietnam (1993), Uganda (1994), Ecuador (1997).
+ </td>
+</tr>
+<tr>
+<td><b>EIA requirements and procedures applied by international financial and aid agencies</b>
+ </td>
+<td>Providing loans and implementing projects in developing countries.
+ </td>
+</tr>
+<tr>
+<td><b>Amendment of EC Directive on EIA (1997)</b>
+ </td>
+<td>Required all member states to be in compliance by 1999; also being
+transposed into the EIA laws of certain countries in transition, which
+are in the process of accession to the European Union.
+ </td>
+</tr>
+<tr>
+<td><b>EC Directive on SEA of certain plans and programmes (2001)</b>
+ </td>
+<td>To be implemented by member states by 2004.
+ </td>
+</tr>
+<tr>
+<td><b>UNECE (or Espoo) Convention on EIA in a Transboundary Context (1991)</b>
+ </td>
+<td>Entered into force in 1997 as the first EIA-specific international treaty.
+ </td>
+</tr>
+<tr>
+<td><b>Doha Ministerial Declaration</b>
+ </td>
+<td>Encourages countries to share expertise and experience with Members
+wishing to perform environmental reviews at the national level (November
+ 2001).
+ </td>
+</tr>
+<tr>
+<td><b>UNECE (or Aarhus) Convention on Access to Information, Public
+Participation in Decision Making and Access to Justice in Environmental
+Matters (1998)</b>
+ </td>
+<td>Covers the decisions at the level of projects and plans, programmes
+and policies and, by extension, applies to EIA and SEA (Articles 6 and 7
+ respectively refer).
+ </td>
+</tr>
+</tbody>
+</table>
+<p>Every EIA system is distinctive to some degree, reflecting the
+political system of a country. An EIA framework or components from one
+country (or international organisation) may not be readily imported into
+ another, at least without significant adaptation. The information
+gathered during the Training Needs Analysis should help in identifying
+current and needed activities in the development of an EIA system (see <a title="UNEP EIA Training Resources Manual" target="_blank" href="http://www.unep.ch/etu/publications/EIAMan_2edition_toc.htm" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.unep.ch');">UNEP EIA Training Resource Manual</a>).
+</p>
+<p>What are the key features to look for, and how do they differ? The
+table below provides a framework for examining EIA systems. It can be
+used to develop a profile of the key provisions that apply, including:
+</p>
+<ul>
+<li>the designation of an authority responsible for overseeing the implementation of EIA procedure;
+ </li>
+<li>the requirement for public participation, and whether it is a mandatory or discretionary procedure; and
+ </li>
+<li>procedural checks and balances for EIA quality control, comprising
+key stages of the EIA process (outlined in the EIA flow chart from the
+previous section).
+ </li>
+</ul>
+<p>The matrix will be most useful when used to compare the EIA systems
+of countries in the same region. When completed, the table can be used
+to identify directions in which legal, policy and institutional
+arrangements might be strengthened. In some developing countries for
+example the arrangements for public participation made by individual
+countries may vary significantly, reflecting different traditions and
+styles of governance. Some countries have established a separate EIA
+authority; in others the EIA process is administered by the environment
+department or by the planning authority. No single EIA model is
+appropriate for all countries.
+</p>
+<table>
+<caption><b>Analysing legal, policy and institutional arrangements</b></caption>
+<thead>
+<tr><th style="width: 16%; background-color: rgb(184, 193, 212);"><b>Country </b>
+ </th>
+<th style="width: 16%;"><b>Type of EIA Authority</b>
+ </th>
+<th style="width: 16%; background-color: rgb(184, 193, 212);"><b>Legal provision Yes/No</b>
+ </th>
+<th style="width: 16%;"><b>Mandatory compliance Yes/No</b>
+ </th>
+<th style="width: 16%; background-color: rgb(184, 193, 212);"><b>Requirement for public participation Yes/No</b>
+ </th>
+<th style="width: 16%;"><b>Procedural checks and balances Yes/No identify types*</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="6"><i>*Refer to stages of the flow chart on the verso of the Topic Divider</i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+</tr>
+<tr>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+</tr>
+<tr>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+<td>
+
+ </td>
+</tr>
+</tbody>
+</table>
+<div class="flvPlayer"> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" height="260" width="320"><param name="movie" value="http://eia.unu.edu/flvplayer.swf?file=http://eia.unu.edu/course/video/2a_eia_legal_systems.flv&amp;autoStart=false;"><param name="quality" value="high"><param name="wmode" value="transparent"><embed src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/flvplayer.swf" quality="high" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="260" width="320"><br>
+ </object></div>
+<p></p>
+<p>Finally, consideration also can be given to the extent to which SEA
+or a near equivalent process is in place. An increasing number of
+developed countries and countries in transition now make formal
+provision for SEA of policies, plans and programmes. Many developing
+countries also have planning systems that include elements of SEA. The
+legal, policy and institutional arrangements for SEA are more varied
+than those for project EIA (see <a title="SEA course module" target="_blank" href="http://sea.unu.edu/">SEA Open Educational Resources</a>).
+</p>
+<p>Two main types of legal provision are made for EIA:
+</p>
+<ul>
+<li>general environmental or resource management law, which incorporates EIA requirements and procedure; and
+ </li>
+<li>an EIA specific law, which can either be comprehensive or take the form of a framework or enabling statute.
+ </li>
+</ul>
+<p>Selected examples of national and international EIA systems are given
+ below to illustrate legal, policy and institutional arrangements that
+are of particular interest. These include the EIA components and
+responsibilities that apply internationally under certain treaties or as
+ result of the lending requirements of the major development banks.
+Their geographical scope of application varies and not all aspects will
+be relevant to particular countries.
+</p>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:40 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=109#comments" title="Comment on 2-2 About EIA Systems">Comments (5)</a> </div>
+
+</div>
+
+
+<h2 id="comments">5 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-286">
+ <p>It is really an interesting course and indeed helpful for my Master
+in Sustainable Environmental Management. Can’t it be accessible in one
+zip file which could be downloaded and saved.</p>
+<p>Thanks again for making the course accessible</p>
+ <p><cite>Comment by Rani — April 17, 2007 @ <a href="#comment-286">4:32 am</a></cite> </p>
+ </li>
+
+ <li id="comment-288">
+ <p>Hi Rani.</p>
+<p>Yes indeed, we are looking into how best to create a downloadable
+version for those persons who do not have regular access to the
+Internet.</p>
+<p>Brendan Barrett<br>
+UNU</p>
+ <p><cite>Comment by brendan — April 24, 2007 @ <a href="#comment-288">10:21 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-7377">
+ <p>The course is content is excellent for revision with good structure and references. Very useful.</p>
+ <p><cite>Comment by <a href="http://www.golder.com/" onclick="javascript:pageTracker._trackPageview('/outbound/commentauthor/www.golder.com');" rel="external nofollow" class="url">susan evans</a> — May 31, 2008 @ <a href="#comment-7377">12:04 am</a></cite> </p>
+ </li>
+
+ <li id="comment-30584">
+ <p>Excellent course material, the content is approached in a very
+clear and defined manner which is excellent for revision. It identifies
+key points which are valuable for essay type questions. I am currently
+doing my Masster in Energy and one of the module is Environmental Impact
+ Assessment. Would appreciate a downloadable copy.</p>
+ <p><cite>Comment by Ayaz Bauhal — April 5, 2009 @ <a href="#comment-30584">10:28 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-55895">
+ <p>excellent learning resource, provides detailed, up to date information and a reference guide.</p>
+ <p><cite>Comment by aduh ufuoma — July 13, 2011 @ <a href="#comment-55895">9:28 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=109"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="109" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-2%20About%20EIA%20Systems_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'109'});
+var load_cmc = function(){linktracker_init(3787197,109,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/flvplayer.swf b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/flvplayer.swf
new file mode 100644
index 0000000..c230d33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/flvplayer.swf
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript.html
new file mode 100644
index 0000000..351b3de
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuuyEhB_u4fSuQgw17X3UvahMtWvIZqLzPYqTCBIdCiegsSA4kU9Po72gPrL0Y-P8um_QZ-4Cpcv0VPHyIfU39o5syOtMERn3CvS7Mit8upMzG7Tvn2h1CXlLD1_4aguG5Lf9zwNqL7WSbIjqB8i-DqLutHlyOsBIDMzfJd3k-R9zF8Q_sA" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuuyEhB_u4fSuQgw17X3UvahMtWvIZqLzPYqTCBIdCiegsSA4kU9Po72gPrL0Y-P8um_QZ-4Cpcv0VPHyIfU39o5syOtMERn3CvS7Mit8upMzG7Tvn2h1CXlLD1_4aguG5Lf9zwNqL7WSbIjqB8i-DqLutHlyOsBIDMzfJd3k-R9zF8Q_sA&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript_data/image.jpg
new file mode 100644
index 0000000..a4be31e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-2 About EIA Systems_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation.html
new file mode 100644
index 0000000..f3c8ae9
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation.html
@@ -0,0 +1,477 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=110">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 297px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110 current_page_item"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-110">
+ <h1 class="storytitle">2-3 EIA Policy and Legislation <a href="http://eia.unu.edu/course/?page_id=110" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>Examples of EIA legislation are available in the <a title="EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/">EIA Wiki</a> under <a title="EIA Systems" target="_blank" href="http://eia.unu.edu/wiki/index.php/EIA_Systems">EIA Systems</a>. Those specific legislation that have set precedents or have been used by other countries include:
+</p>
+<ul>
+<li><a title="United States EIA System" target="_blank" href="http://eia.unu.edu/wiki/index.php/United_States">US National Environmental Policy Act (NEPA, 1969)</a>
+ </li>
+<li><a title="New Zealand EIA System" target="_blank" href="http://eia.unu.edu/wiki/index.php/New_Zealand">New Zealand Resource Management Act (RMA, 1991)</a>
+ </li>
+<li><a title="Canada EIA System" target="_blank" href="http://eia.unu.edu/wiki/index.php/Canada">Canadian Environmental Assessment Act (CEAA, 1993; proclaimed in 1995)</a>
+ </li>
+<li><a href="http://eia.unu.edu/wiki/index.php/European_Union">European Commission (EC) Directive on EIA (1985, amended 1997)</a>
+ </li>
+</ul>
+<p>The requirements of the Directive are also reflected in the EIA
+legislation, policy and institutional arrangements of countries beyond
+the boundaries of the European Union, notably by applicant countries of
+Central and Eastern Europe (CEE) which are bringing their own EIA
+systems into line with them. In addition, the Directive can be expected
+to influence EIA law making in other CEE countries in transition and may
+ have a more generalised influence as a relatively standardised,
+commonly accepted, minimum process for EIA.
+</p>
+<p>The current Directive (97/11/EC) amends the earlier EIA Directive (85/337/EEC) and the key provisions include:
+</p>
+<ul>
+<li>broad definition of the effects to be considered
+ </li>
+<li>mandatory application for specified projects
+ </li>
+<li>requirement to submit an EIA report
+ </li>
+<li>types of information to be provided by developer
+ </li>
+<li>outline of alternatives studied and reasons
+ </li>
+<li>submission to be made available for public comment
+ </li>
+<li>results of consultations and information must be taken into consideration in decision-making
+ </li>
+<li>content and reasons for decisions made public detailed arrangements for public consultation to be drawn up by Member States
+ </li>
+</ul>
+<p><font size="2"><b>International environmental law and policy of relevance to EIA</b></font>
+</p>
+<p>As demonstrated, significant developments have taken place in
+international environmental law and policy which are relevant to or
+applicable by the EIA systems of all countries. These can be divided
+into:
+</p>
+<ul>
+<li>non-binding instruments, such as the Rio Declaration, that establish
+ important principles for sustainable development, including those which
+ need to be reflected in EIA arrangements (e.g. the application of the
+precautionary principle);
+ </li>
+<li>legal conventions and treaties related to environmental protection
+at the global or regional level, which carry obligations for signatory
+countries that may be met through EIA arrangements; and
+ </li>
+<li>legal conventions and protocols that apply specifically to EIA
+arrangements – of which the Espoo Convention is the most notable
+example.
+ </li>
+</ul>
+<p>A number of international environmental agreements establish
+substantive obligations on the countries that ratify them . The
+Conventions on Climate Change and Biological Change are flagship
+agreements because of their global scope, the importance of the issues
+that are addressed and their ratification by a large number of
+countries. EIA is specified as a mechanism for implementing certain
+aspects of both agreements. More generally, it can ensure that the
+proposed actions of signatory countries are in compliance with these and
+ other <a title="International Environmental Agreements - EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/index.php/International_Environmental_Agreements">international environmental agreements</a> (including those listed in the <a title="EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/">EIA Wiki</a>)<span style="background-color: rgb(255, 0, 0);"></span>.
+</p>
+<p>
+
+</p>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:42 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=110#respond" title="Comment on 2-3 EIA Policy and Legislation">Comments (0)</a> </div>
+
+</div>
+
+
+<h2 id="comments">No Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+ <p>No comments yet.</p>
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=110"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="110" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-3%20EIA%20Policy%20and%20Legislation_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'110'});
+var load_cmc = function(){linktracker_init(3787197,110,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript.html
new file mode 100644
index 0000000..aa2322d
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuvXM_Er6WkC-Ef68x7ZeKgxJ-3B6oZjG3S8efIrWtE4g4JBBhWcaqOGrfrcs8cfdDZIXfcwlBkOiAh8DHms50o8HldMWpcwrlx7KqjgoIQBcPExp_bMb3SLEajMZjLr6JEelSE7ruhFNTMm6wALZHKJFsSQx1ZijmSPS9cg3sp0iSQOfZY" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuvXM_Er6WkC-Ef68x7ZeKgxJ-3B6oZjG3S8efIrWtE4g4JBBhWcaqOGrfrcs8cfdDZIXfcwlBkOiAh8DHms50o8HldMWpcwrlx7KqjgoIQBcPExp_bMb3SLEajMZjLr6JEelSE7ruhFNTMm6wALZHKJFsSQx1ZijmSPS9cg3sp0iSQOfZY&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript_data/image.jpg
new file mode 100644
index 0000000..1ab3d64
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-3 EIA Policy and Legislation_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations.html
new file mode 100644
index 0000000..445cf7a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations.html
@@ -0,0 +1,623 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=111">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 297px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111 current_page_item"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-111">
+ <h1 class="storytitle">2-4 EIA Requirements of International Organisations <a href="http://eia.unu.edu/course/?page_id=111" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>The World Bank and the regional development banks, such as the
+African Development Bank, Asian Development Bank, European Bank for
+Reconstruction and Development, and Inter-American Development Bank, now
+ have well-established EIA procedures, which apply to their lending
+activities and projects undertaken by borrowing countries. Although
+their operational policies and requirements vary in certain respects,
+the development banks follow a relatively standard procedure for the
+preparation and approval of an EIA report. This procedure generally
+follows the stages outlined in the flow chart shown on the verso of the
+topic divider. Borrowing countries are responsible for the preparation
+of the EIA, and this requirement possibly more than any other has
+influenced the introduction and development of EIA in many developing
+countries.
+</p>
+<p>The EIA policies and arrangements of the development banks remain
+important, especially in countries that have weak or non-existent
+domestic arrangements. Recently, the World Bank has made a number of
+changes to make the application of its EIA procedure more systematic,
+notably through its linkage to new environmental and social safeguard
+policies. In addition, the Bank’s broader environmental policy has
+moved from a ‘do no harm’ approach to minimise the adverse effects
+of its projects to the use of SEA as part of a strategy of promoting
+long-term sustainability and integrating environment into sector
+programmes and macro policies (see table below).
+</p>
+<table>
+<caption><b>The World Bank environmental agenda</b></caption>
+<thead>
+<tr><th style="width: 25%;"><b>Policy</b>
+ </th>
+<th style="width: 75%; background-color: rgb(184, 193, 212);"><b>Aims</b>
+ </th>
+</tr></thead>
+<tfoot>
+<tr><td colspan="2"><i>Source: World Bank (1999: 8-10) </i>
+ </td>
+</tr></tfoot>
+<tbody>
+<tr>
+<td>Do-No-Harm
+ </td>
+<td>To mitigate the potential adverse effects of the Bank’s investment
+ projects on the environment and vulnerable populations, EIA procedures
+and safeguard policies are applied. In many cases, these have
+contributed to better project design and environmental management plans
+have helped to improve project implementation.
+ </td>
+</tr>
+<tr>
+<td>Targeted Environmental Assistance
+ </td>
+<td>To foster long-term environmental sustainability and improve
+conditions in developing countries, designated Bank projects target the
+following areas: sustainable natural resource management, including
+watershed protection and biodiversity conservation; pollution management
+ and urban environmental improvements; environmental institution and
+capacity building, and global environmental actions, in accordance with
+international environmental conventions and commitments.
+ </td>
+</tr>
+<tr>
+<td>‘Mainstreaming’ the Environment at the Level of Policy and Programmes
+ </td>
+<td>To integrate environmental concerns at the macro level, the Bank has
+ reviewed the policies of the energy, rural development and other
+sectors, established an environmental framework for its country
+assistance strategies and intends to make greater use of SEA at the
+programme and regional level.
+ </td>
+</tr>
+</tbody>
+</table>
+<p>Many countries provide various types of guidance on how to apply
+their EIA procedure. Where the guidance is official, it is usually
+prepared by the overseeing authority to ensure compliance with EIA
+requirements. This material is aimed primarily at the proponent,
+government agencies and others with designated responsibility for
+implementation of EIA arrangements. In certain countries, procedural
+guidance is oriented more toward promoting EIA good practice for key
+stages and activities of the process, such as screening and scoping.
+</p>
+<p>When procedural guidance is not available, it may be developed by
+reference to guidelines prepared by other countries or international
+agencies. There are many examples on which to draw. A useful starting
+point is the <i>IIED Directory of Impact Assessment Guidelines</i> (see
+references). It contains numerous entries organised by country, sector
+and agency, and includes guidelines issued by development banks,
+bilateral-donor, inter-governmental and UN organisations. (More
+specialised guidance on appropriate EIA methodology, and applications to
+ particular types of projects and areas can be found in the World
+Bank’s <i>Environmental Assessment Sourcebook</i>).
+</p>
+<p>In many jurisdictions, more than one set of EIA procedures may apply
+to a proposal. The lack of coherence between the EIA requirements of
+various governments or agencies can lead to uncertainty, confusion and
+added expense for proponents. Problems commonly occur when:
+</p>
+<ul>
+<li>countries receive aid from a number of donors, each having its own prescribed assessment process; or
+ </li>
+<li>a proposal is transboundary in nature, requiring compliance with EIA
+ procedures in two or more countries, states or levels of government
+(see <a title="Espoo Convention - EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/index.php/Espoo_Convention">Espoo Convention</a> in the EIA Wiki).
+ </li>
+</ul>
+<p>The problems of coherence of EIA for international bilateral aid were
+ addressed by the Working Party of the Development Assistance Committee
+of the OECD. A practical guide on this subject was prepared to aid both
+officials in bilateral donor agencies and their counterparts in
+developing countries. It summarises the various EIA procedures used by
+the different agencies and provides two key means of promoting
+coherence:
+</p>
+<ul>
+<li>a framework Terms of Reference for the EIA of development assistance projects; and
+ </li>
+<li>a comprehensive checklist for managing EIA.<br>
+
+ </li>
+</ul>
+<p>Experience in many countries indicates that the foundations of an
+effective EIA system are established by the following arrangements:
+</p>
+<ul>
+<li>explicit basis in law and regulation;
+ </li>
+<li>clear statement of objective(s) and requirement(s);
+ </li>
+<li>mandatory compliance and enforcement;
+ </li>
+<li>comprehensive scope of application to proposals with potentially significant impacts;
+ </li>
+<li>prescribed process of steps and activities;
+ </li>
+<li>provision for public consultation and access to information; and
+ </li>
+<li>linkage to project authorisation, permitting and condition setting.
+ </li>
+</ul>
+<p>In terms of legal provision, aspects of specific importance include:
+</p>
+<ul>
+<li>broad definition of the environment and ‘effects’;
+ </li>
+<li>duty to avoid, mitigate or remedy adverse effects arising from an activity;
+ </li>
+<li>requirement for an EIA report to specify mitigation measures the proponent intends to apply;
+ </li>
+<li>procedural guidance on compliance and good practice in applying EIA arrangements; and
+ </li>
+<li>giving reasons for decisions on proposals subject to EIA.
+ </li>
+</ul>
+<p>These components can be used to evaluate how current EIA systems
+measure up against accepted standards for law, policy and institutional
+arrangements. Where these pre-requisites are in place, they do not
+guarantee, in themselves, good EIA practice and effective performance.
+Other factors may intervene. However, where the basic arrangements are
+inadequate, then the EIA process is very unlikely to lead in the
+direction of good outcomes.
+</p>
+<p>In developing countries experience has shown a number of underlying
+conditions will determine whether and how an EIA system is instituted.
+These are interrelated and reinforcing, and include:
+</p>
+<ul>
+<li>a functional legal regime;
+ </li>
+<li>sound administration and flexible policy-making;
+ </li>
+<li>stakeholder understanding of the aims of the process and its potential benefits;
+ </li>
+<li>political commitment;
+ </li>
+<li>institutional capacity for implementation;
+ </li>
+<li>adequate technical capacity, data and information;
+ </li>
+<li>public involvement; and
+ </li>
+<li>financial capacity.
+ </li>
+</ul>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:44 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=111#comments" title="Comment on 2-4 EIA Requirements of International Organisations">Comments (4)</a> </div>
+
+</div>
+
+
+<h2 id="comments">4 Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+<ol id="commentlist">
+
+ <li id="comment-11444">
+ <p>I am very happy for these application because i work in
+environmental affairs ajency ( as aresearcher ) this information is very
+ important for us thank you</p>
+ <p><cite>Comment by amal fawzy — August 10, 2008 @ <a href="#comment-11444">6:28 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-32476">
+ <p>Hi, I am a geography lecturer and interested in attaining
+international qualifications on EIA as per the module above. Do you do
+some training on this course? Kindly provide with more information.</p>
+<p>Kind regards<br>
+T. Kibutu</p>
+ <p><cite>Comment by Dr Thomas N. Kibutu — June 24, 2009 @ <a href="#comment-32476">12:19 am</a></cite> </p>
+ </li>
+
+ <li id="comment-32579">
+ <p>Dear Dr. Kibutu,<br>
+This is an open educational resource and you are free to use it.
+However, the UNU does not offer a qualification in EIA. You may want to
+contact the International Impact Assessment Association to learn more
+about possible courses.</p>
+<p>Brendan Barrett</p>
+ <p><cite>Comment by brendan — June 30, 2009 @ <a href="#comment-32579">10:22 pm</a></cite> </p>
+ </li>
+
+ <li id="comment-81471">
+ <p>AM a proffessional Environmentalist workin as an Environment Officer
+ with Winrock International (NUDEIL-USAID funded Program), i would like
+to do more proffessional courses in EIA. Please advise and help where
+possible and also alert me of the scholarship opportunities and how to
+apply.</p>
+ <p><cite>Comment by MUKIIBI — August 10, 2012 @ <a href="#comment-81471">9:45 pm</a></cite> </p>
+ </li>
+
+
+</ol>
+
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=111"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="111" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-4%20EIA%20Requirements%20of%20International%20Organisations_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'111'});
+var load_cmc = function(){linktracker_init(3787197,111,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript.html
new file mode 100644
index 0000000..0030369
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_Vuu8HtWjJqHTNCmC1BkfYle-fOg5WnLJ6fzwyPDE3PBrUTkxz10-3_3uK5NHoRS3PsM8phXaagdAHNWX9GcmGpbqjP1enFLLp9YjrytqM8rF3OUnUeDfk_a-Em-ARZjAdwGbxWRyuIU21xQIo1n_vDOrVbKmQ09uP0YTVeRSiZh2TQdqLuk" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_Vuu8HtWjJqHTNCmC1BkfYle-fOg5WnLJ6fzwyPDE3PBrUTkxz10-3_3uK5NHoRS3PsM8phXaagdAHNWX9GcmGpbqjP1enFLLp9YjrytqM8rF3OUnUeDfk_a-Em-ARZjAdwGbxWRyuIU21xQIo1n_vDOrVbKmQ09uP0YTVeRSiZh2TQdqLuk&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript_data/image.jpg
new file mode 100644
index 0000000..5fa451a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-4 EIA Requirements of International Organisations_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System.html
new file mode 100644
index 0000000..d3ac3c4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System.html
@@ -0,0 +1,594 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=112">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 297px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112 current_page_item"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-112">
+ <h1 class="storytitle">2-5 Principles for a Functional EIA System <a href="http://eia.unu.edu/course/?page_id=112" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>Legislation should make clear and explicit provision for the EIA
+process and identify the responsibilities of the various participants.
+It needs to be framed specifically to achieve the goals or outcomes that
+ have been identified and incorporate provision for periodic review (to
+allow for the lessons of experience, changing societal expectations and
+new demands). A functional legal system is needed if EIA legislation is
+to be implemented effectively.
+</p>
+<p><font size="2"><b>Sound administration and flexible policy-making</b></font>
+</p>
+<p>The legal and institutional arrangements for EIA need to be
+implemented fairly, consistently and efficiently. EIA policy should be
+developed flexibly and its effectiveness monitored, giving particular
+attention to the following factors:
+</p>
+<ul>
+<li>the reasons for introducing EIA and the problems that it is meant to resolve;
+ </li>
+<li>the goals of the EIA process and how their achievement can be measured;
+ </li>
+<li>the most appropriate approaches to implementing, enforcing and monitoring the outcomes of the EIA process; and
+ </li>
+<li>mechanisms for reviewing and adapting the EIA process to ensure that it continues to meet needs.
+ </li>
+</ul>
+<p><font size="2"><b>Stakeholder perception of the aims and benefits of the process</b></font>
+</p>
+<p>It is important for all stakeholders to have a realistic
+understanding of the role that EIA is intended to play in development
+approvals. Also, in order to ensure continued support for the EIA
+process, its benefits need to be explicitly recognised and acknowledged,
+ and if necessary, action taken to add value (see above).
+</p>
+<p><font size="2"><b>Political commitment</b></font>
+</p>
+<p>The EIA process cannot succeed in its aims without political
+commitment, public support and adequate resources. Poorer developing
+countries with weak economies and/or unstable political conditions might
+ need to gradually introduce or strengthen their EIA systems.
+</p>
+<p><font size="2"><b>Institutional capacity</b></font>
+</p>
+<p>The successful operation of an EIA system requires the responsible
+institutions to have the capability to carry out the key functions and
+activities. Otherwise, even if EIA legislation is in place, its
+potential benefits will not be delivered. Even where institutional
+capacity is sufficient, particular care may need to be taken to
+facilitate good communication, coordination and cooperation between the
+various government departments responsible for development and
+environmental management.
+</p>
+<p><font size="2"><b>Technical capacity, data and information</b></font>
+</p>
+<p>In particular, the successful operation of the EIA system depends
+upon the availability of qualified people with the technical skills and
+expertise to carry out the research, analysis and preparation of an EIA
+report to the level necessary to inform decision-making. The quality of
+technical work also reflects upon the availability of baseline data and
+information on the natural environment, and the research and education
+system that is in place in a particular country.<br>
+
+</p>
+<p></p>
+<p><font size="2"><b>Public involvement</b></font>
+</p>
+<p>Although attention to technical matters is essential, public
+involvement is crucial to identifying the issues and information that
+may be of importance in EIA. Local knowledge also may be of considerable
+ benefit to the development and viability of a project. Many projects
+have failed because they did not take into account local or traditional
+factors or because they failed to gain public acceptance and support.
+</p>
+<p><font size="2"><b>Financial support</b></font>
+</p>
+<p>Part of the political commitment to the EIA process is the provision
+of adequate funds to administer the process and carry out required
+activities. Where necessary, this commitment should include funds for
+EIA capacity building and training. Often, too, there is a need to
+provide funding for public involvement programmes, especially in cases
+where major projects result in involuntary resettlement or other types
+of social dislocation.
+</p>
+<p>Generally, the need for these programmes is greatest where financial
+resources are scarcest. Realistically, in many cases progress will be
+limited without international assistance. In the long term, adequate
+funding will depend upon the recognition of the benefits that the EIA
+process brings to a country. These benefits need to be recorded (such as
+ in case studies) so that they are available for later use.
+</p>
+<p> The UN Economic Commission for Europe (UNECE) has developed a number
+ of guidelines related to the provision of legal, policy and
+institutional arrangements in the EIA systems of member countries (see <a title="UNECE Principles for Implementation of EIA - EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/index.php/UNECE_Principles_for_Implementation_of_EIA">UNECE Principles for Implementation of EIA</a>
+ in the EIA Wiki). If appropriate, review or provide a copy of these to
+the participants and adapt or add to them to meet the needs of the local
+ situation. Criteria for choosing and customising an EIA system to suit
+are also available (see <a title="Criteria for Choice of EIA Process - EIA Wiki" target="_blank" href="http://eia.unu.edu/wiki/index.php/Criteria_for_Choice_of_EIA_Process">Criteria for Choice of EIA Process</a> in the EIA Wiki).<br>
+
+</p>
+<p><font size="2"><b>Getting ready</b></font>
+</p>
+<p>The development or modification of a country’s EIA procedures requires:<br>
+
+</p>
+<ul>
+<li>gaining the support of government;
+ </li>
+<li>establishing the pre-conditions noted in the previous section;
+ </li>
+<li>understanding other planning and regulatory processes and their
+relationship with the EIA system so as to avoid duplication of
+requirements and functions;
+ </li>
+<li>consideration of the relative strengths and weaknesses of legal, policy and institutional arrangements;&nbsp;
+ </li>
+<li>identification of appropriate means of implementing them; and
+ </li>
+<li>taking account of key trends and directions for EIA development and
+their relevance to the political, social and economic circumstances.
+ </li>
+</ul>
+<p><font size="2"><b>Steps towards establishing an EIA system</b></font>
+</p>
+<p>A number of steps can be taken in adopting or adapting a national EIA
+ system to meet the needs of a particular country, including the
+following:<br>
+
+</p>
+<ul>
+<li>establish the goals and objectives of the EIA process;
+ </li>
+<li>review EIA systems established in neighbouring and other countries,
+especially those that are similar in nature and level of development;
+ </li>
+<li>identify, and cater for, international obligations and commitments
+such as those arising from ratifying the Conventions on Biological
+Diversity and Climate Change;
+ </li>
+<li>learn from the experience of others (consider international reviews
+such as the effectiveness study but also look for regional examples);
+ </li>
+<li>incorporate features that will facilitate the move towards sustainability;
+ </li>
+<li>identify appropriate standards and procedures;
+ </li>
+<li>develop trial guidelines to test the system in practice;
+ </li>
+<li>draft or revise the legislation necessary to implement the necessary changes; and
+ </li>
+<li>incorporate measures to appropriately monitor and review the EIA
+process to ensure that it is working as intended, and, where necessary,
+adapt it to meet new requirements and needs of the country.
+ </li>
+</ul>
+<p>Experience with the operation of EIA systems has generated a number
+of ‘rules of thumb’ that may be generally applicable or useful when
+adopting or adapting legal, policy and institutional arrangements.
+</p>
+<p><font size="2"><b>Developing ‘Rules of Thumb’</b></font>
+</p>
+<p>Consider the following in developing the list:<br>
+
+</p>
+<ul>
+<li>Without a clear legal and institutional framework, EIA is ad hoc and the benefits are lost or reduced.
+ </li>
+<li>EIA relies on and is assisted by other environmental policy and
+regulatory systems which set objectives and standards (e.g. for ambient
+air quality, emission and discharge limits etc.)
+ </li>
+<li>Other EIA systems always need to be adapted to the ‘political
+culture’ of a specific country, particularly in the area of public
+involvement.
+ </li>
+<li>EIA should apply equally to private and publicly funded projects; their environmental significance is what matters.
+ </li>
+<li>In order to achieve maximum effectiveness, the EIA process should be
+ integrated with the project cycle at the earliest pre-feasibility
+stage.
+ </li>
+<li>A quick start up to gain ‘hands on’ experience with EIA
+arrangements is usually preferable to lengthy preparatory studies.&nbsp;
+ </li>
+<li>This approach will pay most dividends when it is part of an explicit attempt to ‘learn and adapt as you go’.&nbsp;
+ </li>
+<li>Even though institutional capability may be at an early stage, EIA
+can still lead to substantial benefits in the form of better
+environmental protection.&nbsp;
+ </li>
+<li>When proponents, the government and the public are experienced in
+the process they are more likely to have realistic expectations of the
+process and its outcomes.
+ </li>
+</ul>
+<p>&nbsp;</p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 12:45 pm </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=112#respond" title="Comment on 2-5 Principles for a Functional EIA System">Comments (0)</a> </div>
+
+</div>
+
+
+<h2 id="comments">No Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+ <p>No comments yet.</p>
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=112"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="112" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-5%20Principles%20for%20a%20Functional%20EIA%20System_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'112'});
+var load_cmc = function(){linktracker_init(3787197,112,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript.html
new file mode 100644
index 0000000..bf45a98
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_VuuwytBV-D-zuddUzojc6JcHNi8CKo7_ZRbRCb6HcyA3Q3pwcYMFfZKvUehntFfZguQyWI_6BChkG1AUcEkl5MNuCSa3k0v8ytedfJiq1xtDt_PB77sGknZqH_mx6PB7LHL6hKcaj8RrAfdWfFSoRSFGaRunoulNPKHecTabJGBJoq9s0gk" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_VuuwytBV-D-zuddUzojc6JcHNi8CKo7_ZRbRCb6HcyA3Q3pwcYMFfZKvUehntFfZguQyWI_6BChkG1AUcEkl5MNuCSa3k0v8ytedfJiq1xtDt_PB77sGknZqH_mx6PB7LHL6hKcaj8RrAfdWfFSoRSFGaRunoulNPKHecTabJGBJoq9s0gk&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript_data/image.jpg
new file mode 100644
index 0000000..d0dc791
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-5 Principles for a Functional EIA System_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary.html
new file mode 100644
index 0000000..5356ec5
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary.html
@@ -0,0 +1,416 @@
+<!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"><head profile="http://gmpg.org/xfn/11">
+ <title>Environmental Impact Assessment Course Module » 2-6 Summary</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="generator" content="WordPress 2.8.4"> <!-- leave this for stats please -->
+
+ <style type="text/css" media="screen">
+ @import url( http://eia.unu.edu/course/wp-content/themes/EIA/style.css );
+ </style>
+
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/prototype.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/moo.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/unu.js"></script>
+ <script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/swfobject.js"></script>
+
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/prototype_002.js" type="text/javascript"></script>
+ <script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/scriptaculous.js" type="text/javascript"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/builder.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/effects.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/dragdrop.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/controls.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/slider.js"></script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/sound.js"></script>
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://eia.unu.edu/course/?feed=rss2">
+ <link rel="alternate" type="text/xml" title="RSS .92" href="http://eia.unu.edu/course/?feed=rss">
+ <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://eia.unu.edu/course/?feed=atom">
+
+ <link rel="pingback" href="http://eia.unu.edu/course/xmlrpc.php">
+ <link rel="alternate" type="application/rss+xml" title="Environmental Impact Assessment Course Module » 2-6 Summary Comments Feed" href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=87">
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://eia.unu.edu/course/xmlrpc.php?rsd">
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://eia.unu.edu/course/wp-includes/wlwmanifest.xml">
+<link rel="index" title="Environmental Impact Assessment Course Module" href="http://eia.unu.edu/course">
+<link rel="up" title="2. Law, Policy and Institutional Arrangements" href="http://eia.unu.edu/course/?page_id=28">
+<meta name="generator" content="WordPress 2.8.4">
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ _uacct = "UA-254067-1";
+urchinTracker();
+</script>
+</head>
+<body>
+
+
+<!-- this is by kouji . system header start ----------- -------------------------------------------->
+
+<div id="main">
+<div id="header"><a href="http://eia.unu.edu/course/?page_id=173"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/logo.jpg" alt="Environmental Impact Assessment - Course Module" height="104" width="957"></a></div>
+<!-- end header -->
+
+<!-- begin sidebar -->
+ <div id="nav">
+<ul id="navul">
+ <li class="page_item page-item-148"><span><a class="h" href="http://eia.unu.edu/course/?page_id=148" title="Welcome">Welcome</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-173"><a href="http://eia.unu.edu/course/?page_id=173" title="Course Introduction">Course Introduction</a></li>
+ <li class="page_item page-item-174"><a href="http://eia.unu.edu/course/?page_id=174" title="Help us to be sustainable">Help us to be sustainable</a></li>
+</ul>
+</li>
+<li class="page_item page-item-25"><span><a class="h" href="http://eia.unu.edu/course/?page_id=25" title="1. Background">1. Background</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-145"><a href="http://eia.unu.edu/course/?page_id=145" title="1-1 Background">1-1 Background</a></li>
+ <li class="page_item page-item-93"><a href="http://eia.unu.edu/course/?page_id=93" title="1-2 Purpose and aims of EIA">1-2 Purpose and aims of EIA</a>
+ <ul>
+ <li class="page_item page-item-149"><a href="http://eia.unu.edu/course/?page_id=149" title="Activity 1A – Introduction to EIA">Activity 1A – Introduction to EIA</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-97"><a href="http://eia.unu.edu/course/?page_id=97" title="1-3 Nature and Scope of environmental issues and impacts">1-3 Nature and Scope of environmental issues and impacts</a></li>
+ <li class="page_item page-item-100"><a href="http://eia.unu.edu/course/?page_id=100" title="1-4 Principles of EIA administration and practice">1-4 Principles of EIA administration and practice</a></li>
+ <li class="page_item page-item-101"><a href="http://eia.unu.edu/course/?page_id=101" title="1-5 Key elements of the EIA process">1-5 Key elements of the EIA process</a>
+ <ul>
+ <li class="page_item page-item-150"><a href="http://eia.unu.edu/course/?page_id=150" title="Activity 1B – Introduction to EIA Practice">Activity 1B – Introduction to EIA Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-102"><a href="http://eia.unu.edu/course/?page_id=102" title="1-6 Costs and benefits of EIA">1-6 Costs and benefits of EIA</a></li>
+ <li class="page_item page-item-175"><a href="http://eia.unu.edu/course/?page_id=175" title="1-7 Summary">1-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-28 current_page_ancestor current_page_parent"><span><a class="h" href="http://eia.unu.edu/course/?page_id=28" title="2. Law, Policy and Institutional Arrangements">2. Law, Policy and Institutional Arrangements</a></span>
+<ul style="overflow: hidden; height: 285px;">
+ <li class="page_item page-item-146"><a href="http://eia.unu.edu/course/?page_id=146" title="2-1 Introduction">2-1 Introduction</a></li>
+ <li class="page_item page-item-109"><a href="http://eia.unu.edu/course/?page_id=109" title="2-2 About EIA Systems">2-2 About EIA Systems</a></li>
+ <li class="page_item page-item-110"><a href="http://eia.unu.edu/course/?page_id=110" title="2-3 EIA Policy and Legislation">2-3 EIA Policy and Legislation</a>
+ <ul>
+ <li class="page_item page-item-151"><a href="http://eia.unu.edu/course/?page_id=151" title="Activity 2A – EIA Systems, Policy and Legislation">Activity 2A – EIA Systems, Policy and Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-111"><a href="http://eia.unu.edu/course/?page_id=111" title="2-4 EIA Requirements of International Organisations">2-4 EIA Requirements of International Organisations</a></li>
+ <li class="page_item page-item-112"><a href="http://eia.unu.edu/course/?page_id=112" title="2-5 Principles for a Functional EIA System">2-5 Principles for a Functional EIA System</a>
+ <ul>
+ <li class="page_item page-item-154"><a href="http://eia.unu.edu/course/?page_id=154" title="Assignment 1 – Legal Requirements for EIA.">Assignment 1 – Legal Requirements for EIA.</a></li>
+ <li class="page_item page-item-152"><a href="http://eia.unu.edu/course/?page_id=152" title="Activity 2B – Localisation of EIA Legislation">Activity 2B – Localisation of EIA Legislation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-87 current_page_item"><a href="http://eia.unu.edu/course/?page_id=87" title="2-6 Summary">2-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-29"><span><a class="h" href="http://eia.unu.edu/course/?page_id=29" title="3. Public involvement">3. Public involvement</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-179"><a href="http://eia.unu.edu/course/?page_id=179" title="3-1 Introduction">3-1 Introduction</a></li>
+ <li class="page_item page-item-129"><a href="http://eia.unu.edu/course/?page_id=129" title="3-2 What is public involvement?">3-2 What is public involvement?</a></li>
+ <li class="page_item page-item-130"><a href="http://eia.unu.edu/course/?page_id=130" title="3-3 Stakeholders involved">3-3 Stakeholders involved</a></li>
+ <li class="page_item page-item-131"><a href="http://eia.unu.edu/course/?page_id=131" title="3-4 Principles of public involvement">3-4 Principles of public involvement</a>
+ <ul>
+ <li class="page_item page-item-153"><a href="http://eia.unu.edu/course/?page_id=153" title="Activity 3A – Public Involvement Principles">Activity 3A – Public Involvement Principles</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-132"><a href="http://eia.unu.edu/course/?page_id=132" title="3-5 Scope of involvement">3-5 Scope of involvement</a></li>
+ <li class="page_item page-item-133"><a href="http://eia.unu.edu/course/?page_id=133" title="3-6 Planning a public involvement programme">3-6 Planning a public involvement programme</a></li>
+ <li class="page_item page-item-134"><a href="http://eia.unu.edu/course/?page_id=134" title="3-7 Public involvement techniques">3-7 Public involvement techniques</a>
+ <ul>
+ <li class="page_item page-item-155"><a href="http://eia.unu.edu/course/?page_id=155" title="Activity 3B – Public Involvement Practice">Activity 3B – Public Involvement Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-135"><a href="http://eia.unu.edu/course/?page_id=135" title="3-8 Arguments for and against public involvement">3-8 Arguments for and against public involvement</a></li>
+ <li class="page_item page-item-180"><a href="http://eia.unu.edu/course/?page_id=180" title="3-9 Summary">3-9 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-30"><span><a class="h" href="http://eia.unu.edu/course/?page_id=30" title="4. Screening">4. Screening</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-181"><a href="http://eia.unu.edu/course/?page_id=181" title="4-1 Introduction">4-1 Introduction</a></li>
+ <li class="page_item page-item-136"><a href="http://eia.unu.edu/course/?page_id=136" title="4-2 Screening procedure">4-2 Screening procedure</a></li>
+ <li class="page_item page-item-137"><a href="http://eia.unu.edu/course/?page_id=137" title="4-3 Project lists for screening">4-3 Project lists for screening</a></li>
+ <li class="page_item page-item-138"><a href="http://eia.unu.edu/course/?page_id=138" title="4-4 Preliminary EIA">4-4 Preliminary EIA</a>
+ <ul>
+ <li class="page_item page-item-156"><a href="http://eia.unu.edu/course/?page_id=156" title="Activity 4A – Screening Basics">Activity 4A – Screening Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-139"><a href="http://eia.unu.edu/course/?page_id=139" title="4-5 Other types of Screening">4-5 Other types of Screening</a></li>
+ <li class="page_item page-item-86"><a href="http://eia.unu.edu/course/?page_id=86" title="4-6 Criteria for the determination of the need for, and level of, EIA">4-6 Criteria for the determination of the need for, and level of, EIA</a>
+ <ul>
+ <li class="page_item page-item-157"><a href="http://eia.unu.edu/course/?page_id=157" title="Activity 4A – Screening Exercise">Activity 4A – Screening Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-182"><a href="http://eia.unu.edu/course/?page_id=182" title="4-7 Summary">4-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-31"><span><a class="h" href="http://eia.unu.edu/course/?page_id=31" title="5. Scoping">5. Scoping</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-185"><a href="http://eia.unu.edu/course/?page_id=185" title="5-1 Introduction">5-1 Introduction</a></li>
+ <li class="page_item page-item-140"><a href="http://eia.unu.edu/course/?page_id=140" title="5-2 Purpose of scoping">5-2 Purpose of scoping</a></li>
+ <li class="page_item page-item-141"><a href="http://eia.unu.edu/course/?page_id=141" title="5-3 Approaches to scoping">5-3 Approaches to scoping</a></li>
+ <li class="page_item page-item-142"><a href="http://eia.unu.edu/course/?page_id=142" title="5-4 Scoping methods">5-4 Scoping methods</a>
+ <ul>
+ <li class="page_item page-item-158"><a href="http://eia.unu.edu/course/?page_id=158" title="Activity 5A – Scoping Basics">Activity 5A – Scoping Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-143"><a href="http://eia.unu.edu/course/?page_id=143" title="5-5 Alternatives and tiering">5-5 Alternatives and tiering</a>
+ <ul>
+ <li class="page_item page-item-159"><a href="http://eia.unu.edu/course/?page_id=159" title="Activity 5B – Scoping in Practice">Activity 5B – Scoping in Practice</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-144"><a href="http://eia.unu.edu/course/?page_id=144" title="5-6 EIA Terms of Reference">5-6 EIA Terms of Reference</a>
+ <ul>
+ <li class="page_item page-item-160"><a href="http://eia.unu.edu/course/?page_id=160" title="Assignment 2 – Scoping Study">Assignment 2 – Scoping Study</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-184"><a href="http://eia.unu.edu/course/?page_id=184" title="5-7 Summary">5-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-32"><span><a class="h" href="http://eia.unu.edu/course/?page_id=32" title="6. Impact analysis">6. Impact analysis</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-121"><a href="http://eia.unu.edu/course/?page_id=121" title="6-1 Implications of the widening environment and sustainability agenda">6-1 Implications of the widening environment and sustainability agenda</a></li>
+ <li class="page_item page-item-122"><a href="http://eia.unu.edu/course/?page_id=122" title="6-2 Impact Identification">6-2 Impact Identification</a></li>
+ <li class="page_item page-item-123"><a href="http://eia.unu.edu/course/?page_id=123" title="6-3 Impact Analysis/Prediction">6-3 Impact Analysis/Prediction</a>
+ <ul>
+ <li class="page_item page-item-191"><a href="http://eia.unu.edu/course/?page_id=191" title="Activity 6A – Impact Analysis Basics">Activity 6A – Impact Analysis Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-186"><a href="http://eia.unu.edu/course/?page_id=186" title="6-4 Characteristics of environmental impacts">6-4 Characteristics of environmental impacts</a>
+ <ul>
+ <li class="page_item page-item-192"><a href="http://eia.unu.edu/course/?page_id=192" title="Activity 6B – Impact Characterisation">Activity 6B – Impact Characterisation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-124"><a href="http://eia.unu.edu/course/?page_id=124" title="6-5 Social Impact Assessment">6-5 Social Impact Assessment</a></li>
+ <li class="page_item page-item-125"><a href="http://eia.unu.edu/course/?page_id=125" title="6-6 Evaluation of impact significance">6-6 Evaluation of impact significance</a></li>
+ <li class="page_item page-item-126"><a href="http://eia.unu.edu/course/?page_id=126" title="6-7 Significance Criteria">6-7 Significance Criteria</a>
+ <ul>
+ <li class="page_item page-item-161"><a href="http://eia.unu.edu/course/?page_id=161" title="Activity 6C – Impact Significance Assessment">Activity 6C – Impact Significance Assessment</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-128"><a href="http://eia.unu.edu/course/?page_id=128" title="6-8 Summary">6-8 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-33"><span><a class="h" href="http://eia.unu.edu/course/?page_id=33" title="7. Mitigation and Impact Management">7. Mitigation and Impact Management</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-117"><a href="http://eia.unu.edu/course/?page_id=117" title="7-1 Link between EIA process and Mitigation">7-1 Link between EIA process and Mitigation</a></li>
+ <li class="page_item page-item-118"><a href="http://eia.unu.edu/course/?page_id=118" title="7-2 Main Elements of Mitigation">7-2 Main Elements of Mitigation</a>
+ <ul>
+ <li class="page_item page-item-162"><a href="http://eia.unu.edu/course/?page_id=162" title="Activity 7A – Mitigation Basics">Activity 7A – Mitigation Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-188"><a href="http://eia.unu.edu/course/?page_id=188" title="7-3 Approaches to Mitigation">7-3 Approaches to Mitigation</a>
+ <ul>
+ <li class="page_item page-item-193"><a href="http://eia.unu.edu/course/?page_id=193" title="Activity 7B – Mitigation of Specific Impacts">Activity 7B – Mitigation of Specific Impacts</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-120"><a href="http://eia.unu.edu/course/?page_id=120" title="7-4 Environmental Management Plan and Mitigation Measures">7-4 Environmental Management Plan and Mitigation Measures</a>
+ <ul>
+ <li class="page_item page-item-163"><a href="http://eia.unu.edu/course/?page_id=163" title="Assignment 3 – Impact Assessment and Mitigation">Assignment 3 – Impact Assessment and Mitigation</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-187"><a href="http://eia.unu.edu/course/?page_id=187" title="7-5 Summary and Conclusions">7-5 Summary and Conclusions</a></li>
+</ul>
+</li>
+<li class="page_item page-item-34"><span><a class="h" href="http://eia.unu.edu/course/?page_id=34" title="8. EIA Reporting">8. EIA Reporting</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-113"><a href="http://eia.unu.edu/course/?page_id=113" title="8-1 What is an EIA Report?">8-1 What is an EIA Report?</a></li>
+ <li class="page_item page-item-114"><a href="http://eia.unu.edu/course/?page_id=114" title="8-2 Typical Elements of an EIA Report">8-2 Typical Elements of an EIA Report</a>
+ <ul>
+ <li class="page_item page-item-164"><a href="http://eia.unu.edu/course/?page_id=164" title="Activity 8A. EIA Reporting Basics">Activity 8A. EIA Reporting Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-115"><a href="http://eia.unu.edu/course/?page_id=115" title="8-3 Shortcomings encountered in Preparing EIA Reports">8-3 Shortcomings encountered in Preparing EIA Reports</a></li>
+ <li class="page_item page-item-116"><a href="http://eia.unu.edu/course/?page_id=116" title="8-4 Guidelines for effective EIA report preparation and production">8-4 Guidelines for effective EIA report preparation and production</a>
+ <ul>
+ <li class="page_item page-item-165"><a href="http://eia.unu.edu/course/?page_id=165" title="Activity 8B – The Non-Technical Summary/Executive Summary">Activity 8B – The Non-Technical Summary/Executive Summary</a></li>
+ <li class="page_item page-item-166"><a href="http://eia.unu.edu/course/?page_id=166" title="Activity 8C – EIA Reporting Practice">Activity 8C – EIA Reporting Practice</a></li>
+ </ul>
+</li>
+</ul>
+</li>
+<li class="page_item page-item-35"><span><a class="h" href="http://eia.unu.edu/course/?page_id=35" title="9. Review of EIA Quality">9. Review of EIA Quality</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-104"><a href="http://eia.unu.edu/course/?page_id=104" title="9-1 Role and Purpose of the EIA Review Process">9-1 Role and Purpose of the EIA Review Process</a></li>
+ <li class="page_item page-item-105"><a href="http://eia.unu.edu/course/?page_id=105" title="9-2 Need for a Systematic Approach">9-2 Need for a Systematic Approach</a></li>
+ <li class="page_item page-item-106"><a href="http://eia.unu.edu/course/?page_id=106" title="9-3 Procedural Aspects">9-3 Procedural Aspects</a></li>
+ <li class="page_item page-item-108"><a href="http://eia.unu.edu/course/?page_id=108" title="9-4 Main Steps in the EIA Review">9-4 Main Steps in the EIA Review</a>
+ <ul>
+ <li class="page_item page-item-167"><a href="http://eia.unu.edu/course/?page_id=167" title="Activity 9A – EIA Quality Basics">Activity 9A – EIA Quality Basics</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-107"><a href="http://eia.unu.edu/course/?page_id=107" title="9-5 Carrying out the review">9-5 Carrying out the review</a>
+ <ul>
+ <li class="page_item page-item-168"><a href="http://eia.unu.edu/course/?page_id=168" title="Activity 9B – EIA Report Quality Assessment Exercise">Activity 9B – EIA Report Quality Assessment Exercise</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-103"><a href="http://eia.unu.edu/course/?page_id=103" title="9-6 Procedures for Evaluating EIA Reports">9-6 Procedures for Evaluating EIA Reports</a>
+ <ul>
+ <li class="page_item page-item-169"><a href="http://eia.unu.edu/course/?page_id=169" title="Assignment 4 – Essay/Project">Assignment 4 – Essay/Project</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-189"><a href="http://eia.unu.edu/course/?page_id=189" title="9-7 Summary">9-7 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-38"><span><a class="h" href="http://eia.unu.edu/course/?page_id=38" title="10. Decision-making">10. Decision-making</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-98"><a href="http://eia.unu.edu/course/?page_id=98" title="10-1 Role of the Decision-makers">10-1 Role of the Decision-makers</a></li>
+ <li class="page_item page-item-99"><a href="http://eia.unu.edu/course/?page_id=99" title="10-2 EIA as part of the Decision-making Process">10-2 EIA as part of the Decision-making Process</a>
+ <ul>
+ <li class="page_item page-item-170"><a href="http://eia.unu.edu/course/?page_id=170" title="Activity 10A – Decision-making: Procedural Considerations">Activity 10A – Decision-making: Procedural Considerations</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-96"><a href="http://eia.unu.edu/course/?page_id=96" title="10-3 Responsibility of the Decision-Makers">10-3 Responsibility of the Decision-Makers</a></li>
+ <li class="page_item page-item-94"><a href="http://eia.unu.edu/course/?page_id=94" title="10-4 Summary">10-4 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-39"><span><a class="h" href="http://eia.unu.edu/course/?page_id=39" title="11. Implementation and Follow-up">11. Implementation and Follow-up</a></span>
+<ul style="overflow: hidden; height: 0px;">
+ <li class="page_item page-item-89"><a href="http://eia.unu.edu/course/?page_id=89" title="11-1 Key Objectives of EIA implementation and follow up">11-1 Key Objectives of EIA implementation and follow up</a></li>
+ <li class="page_item page-item-90"><a href="http://eia.unu.edu/course/?page_id=90" title="11-2 Tools for Environmental Management and Performance Review">11-2 Tools for Environmental Management and Performance Review</a></li>
+ <li class="page_item page-item-88"><a href="http://eia.unu.edu/course/?page_id=88" title="11-3 Monitoring">11-3 Monitoring</a>
+ <ul>
+ <li class="page_item page-item-171"><a href="http://eia.unu.edu/course/?page_id=171" title="Activity 11A – Implementation Management Planning">Activity 11A – Implementation Management Planning</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-91"><a href="http://eia.unu.edu/course/?page_id=91" title="11-4 Environmental Auditing">11-4 Environmental Auditing</a>
+ <ul>
+ <li class="page_item page-item-172"><a href="http://eia.unu.edu/course/?page_id=172" title="Activity 11B – EMP and Audit Programme">Activity 11B – EMP and Audit Programme</a></li>
+ </ul>
+</li>
+ <li class="page_item page-item-190"><a href="http://eia.unu.edu/course/?page_id=190" title="11-5 Evaluation of EIA Effectiveness and Performance">11-5 Evaluation of EIA Effectiveness and Performance</a></li>
+ <li class="page_item page-item-92"><a href="http://eia.unu.edu/course/?page_id=92" title="11-6 Summary">11-6 Summary</a></li>
+</ul>
+</li>
+<li class="page_item page-item-176"><span><a class="h" href="http://eia.unu.edu/course/?page_id=176" title="References">References</a></span></li>
+<li class="page_item page-item-177"><span><a class="h" href="http://eia.unu.edu/course/?page_id=177" title="Definitions">Definitions</a></span></li>
+<li class="page_item page-item-178"><span><a class="h" href="http://eia.unu.edu/course/?page_id=178" title="Credits">Credits</a></span></li>
+
+</ul>
+ <script type="text/javascript">
+ <!-- //
+ UNU.prepareNavigation();
+ //-->
+ </script>
+<form method="get" id="searchform" action="http://eia.unu.edu/course/">
+<div>
+<input name="s" id="s" type="text"><input id="searchbtn" value="Search" type="submit">
+</div>
+</form>
+
+ </div>
+<!-- end sidebar -->
+
+
+
+<div id="content">
+
+<div id="padding">
+
+
+
+<div class="post" id="post-87">
+ <h1 class="storytitle">2-6 Summary <a href="http://eia.unu.edu/course/?page_id=87" rel="bookmark"></a></h1>
+ <div class="storycontent">
+ <p>You have now completed Section 2 of 11 in this Environmental Impact
+ Assessment Course Module. To demonstrate the learning outcomes of this
+Section, check that you are now able to:
+</p>
+<ul>
+<li>Understand the purpose, scope and content of EIA policy and legislation;
+ </li>
+<li>Understand the EIA requirements of International Organisations and relevant International Environmental Agreements;
+ </li>
+<li>Demonstrate understanding of the legal principles underpinning a functional EIA system; and
+ </li>
+<li>Show familiarity with duties placed on local authorities and developers.
+ </li>
+</ul>
+<p></p>
+ </div>
+ <div class="storycontent">
+ </div>
+ <div class="meta">July 26, 2006 <a href="http://eia.unu.edu/course/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> — @ 11:04 am </div>
+ <div class="feedback">
+ <a href="http://eia.unu.edu/course/?page_id=87#respond" title="Comment on 2-6 Summary">Comments (0)</a> </div>
+
+</div>
+
+
+<h2 id="comments">No Comments
+ <a href="#postcomment" title="Leave a comment">»</a>
+</h2>
+
+ <p>No comments yet.</p>
+
+<p><a href="http://eia.unu.edu/course/?feed=rss2&amp;page_id=87"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a>
+ <a href="http://eia.unu.edu/course/wp-trackback.php?p=87" rel="trackback">TrackBack <abbr title="Uniform Resource Identifier">URI</abbr></a>
+</p>
+
+<h2 id="postcomment">Leave a comment</h2>
+
+
+<form action="http://eia.unu.edu/course/wp-comments-post.php" method="post" id="commentform">
+
+
+<p><input name="author" id="author" size="22" tabindex="1" type="text">
+<label for="author"><small>Name (required)</small></label></p>
+
+<p><input name="email" id="email" size="22" tabindex="2" type="text">
+<label for="email"><small>Mail (will not be published) (required)</small></label></p>
+
+<p><input name="url" id="url" size="22" tabindex="3" type="text">
+<label for="url"><small>Website</small></label></p>
+
+
+<!--<p><small><strong>XHTML:</strong> You can use these tags: &lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </small></p>-->
+
+<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
+
+<p>
+<input name="comment_post_ID" value="87" type="hidden">
+</p>
+ <script type="text/javascript">
+ var RecaptchaOptions = { theme : 'white', tabindex : 5 };
+ </script><script type="text/javascript" src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/challenge"></script>
+
+ <noscript class="noscript-show"><span>
+ <iframe src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/noscript.html" frameborder="0" height="300" width="500"></iframe><br>
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input name="recaptcha_response_field" value="manual_challenge" type="hidden">
+ </span></noscript> <div id="recaptcha-submit-btn-area"><input name="submit" id="submit" tabindex="6" class="button" value="Submit Comment" type="submit"></div>
+ <script type="text/javascript">
+ var sub = document.getElementById('submit');
+ sub.parentNode.removeChild(sub);
+ document.getElementById('recaptcha-submit-btn-area').appendChild (sub);
+ document.getElementById('submit').tabIndex = 6;
+ if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') {
+ document.getElementById('comment').value = _recaptcha_wordpress_savedcomment;
+ }
+ </script>
+ <noscript>
+ <style type='text/css'>#submit {display:none;}</style>
+ <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/>
+ </noscript>
+</form>
+
+
+
+
+</div>
+<!-- footer -->
+ <div id="footer">
+ <ul>
+ <li><a href="http://eia.unu.edu/about.html">About</a></li>
+ <li><a href="http://eia.unu.edu/download.html">Download</a></li>
+ <li><a href="http://eia.unu.edu/disclaimer.html">Disclaimer</a></li>
+ <li><a href="http://eia.unu.edu/copyright.html">Copyright</a></li>
+ <li><a href="http://eia.unu.edu/contact.html">Contact</a></li>
+ </ul>
+
+ <div id="university"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/unu_logo_white.gif" alt="United Nations University" height="50" width="109"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/footer_link2.gif" alt="UNEP" height="50" width="40"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/Gvu-logo.gif" alt="GVU" height="50" width="141"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/RMIT.gif" alt="RMIT" height="50" width="106"><img src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/USP.gif" alt="USP" height="50" width="137"></div>
+ </div>
+
+
+ </div>
+ </div>
+
+
+
+<script src="Environmental%20Impact%20Assessment%20Course%20Module%20%C2%BB%202-6%20Summary_files/e-201312.js" type="text/javascript"></script>
+<script type="text/javascript">
+st_go({blog:'3787197',v:'ext',post:'87'});
+var load_cmc = function(){linktracker_init(3787197,87,2);};
+if ( typeof addLoadEvent != 'undefined' ) addLoadEvent(load_cmc);
+else load_cmc();
+</script>
+
+
+</body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/Gvu-logo.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/Gvu-logo.gif
new file mode 100644
index 0000000..55b66cb
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/Gvu-logo.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/RMIT.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/RMIT.gif
new file mode 100644
index 0000000..4f21bf7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/RMIT.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/USP.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/USP.gif
new file mode 100644
index 0000000..891564f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/USP.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/builder.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/builder.js
new file mode 100644
index 0000000..8301999
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/builder.js
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return element;
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e)
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ }
+ });
+ }
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/challenge b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/challenge
new file mode 100644
index 0000000..f36bc33
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/challenge
@@ -0,0 +1,14 @@
+
+var RecaptchaState = {
+ site : '6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq',
+ rtl : false,
+ challenge : '03AHJ_Vut361IxU6MwtK4OR1Dc0wP3DI6oOJX6L3IO6AYMjbrL-v2G6ugou9ibrTmWl1xj4zZrCrt2d83iqV5QtUfNTAYp2EKit4sxIwj9uP-eyzKkekYEqfLkwXXBwQMCKvLwOKVnw9X5OxLDdeSISCathxty1CMYtaI06hYun6P7irSog9P5Zg8',
+ is_incorrect : false,
+ programming_error : '',
+ error_message : '',
+ server : 'http://www.google.com/recaptcha/api/',
+ lang : 'zh-CN',
+ timeout : 1800
+};
+
+document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/controls.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/controls.js
new file mode 100644
index 0000000..5012cb8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/controls.js
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/dragdrop.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/dragdrop.js
new file mode 100644
index 0000000..bf429c2
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/dragdrop.js
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+}
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ var s = Sortable.options(element);
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child)
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ }
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/e-201312.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/e-201312.js
new file mode 100644
index 0000000..acf27b8
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/e-201312.js
@@ -0,0 +1,13 @@
+function st_go(a){var i,u=document.location.protocol+'//stats.wordpress.com/g.gif?host='+escape(document.location.host)+'&rand='+Math.random();for(i in a){u=u+'&'+i+'='+escape(a[i]);}u=u+'&ref='+escape(document.referrer);document.open();document.write("<img id=\"wpstats\" src=\""+u+"\" alt=\"\" />");document.close();}
+function wpcomAddEvent(el,ev,fn){var isIE=window.attachEvent?true:false;if(isIE)el.attachEvent('on'+ev,fn);else if(el.addEventListener)el.addEventListener(ev,fn,false);}
+function linkmousedown(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=true;}
+function linkmouseout(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;m.modo=false;}
+function linkmouseup(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var m=isIE?window.event.srcElement:event.currentTarget;if(m.modo)linktracker_record(event);}
+function linkclick(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");linktracker_record(event);}
+function linktracker_init(b,p){_blog=b;_post=p;if(typeof document.location.host!='undefined')
+var localserver=document.location.host;else
+var localserver=document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/,'$1');var els=document.getElementsByTagName('a');for(var i=0;i<els.length;i++){var href=els[i].href;if(href.match(eval('/^(http(s)?:\\/\\/)?'+localserver+'/')))continue;wpcomAddEvent(els[i],'mousedown',linkmousedown);wpcomAddEvent(els[i],'mouseout',linkmouseout);wpcomAddEvent(els[i],'mouseup',linkmouseup);}}
+function linktracker_record(event){var isIE=window.attachEvent?true:false;event=event?event:(window.event?window.event:"");var b=isIE?window.event.srcElement:event.currentTarget;while(b.nodeName!="A"){if(typeof b.parentNode=='undefined')return;b=b.parentNode;}
+var bh=b.href;var pr=document.location.protocol||'http:';var b=(typeof _blog!='undefined')?_blog:0;var p=(typeof _post!='undefined')?_post:0;var i=new Image(1,1);i.src=pr+'//stats.wordpress.com/c.gif?s=2&b='+b+'&p='+p+'&u='+escape(bh);i.onLoad=function(){cmcVoid();}}
+function cmcVoid(){return;}
+if(typeof _wpdq=="undefined"){var _qevents=_qevents||[];(function(){var elem=document.createElement('script');elem.src=(document.location.protocol=="https:"?"https://secure":"http://edge")+".quantserve.com/quant.js";elem.async=true;elem.type="text/javascript";var scpt=document.getElementsByTagName('script')[0];scpt.parentNode.insertBefore(elem,scpt);})();_qevents.push({qacct:"p-18-mFEk4J448M",labels:"type.wporg"});} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/effects.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/effects.js
new file mode 100644
index 0000000..b8c0259
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/effects.js
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element)
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ })
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ )
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { };
+ var oldOpacity = element.getInlineOpacity();
+ var transition = options.transition || Effect.Transitions.sinoidal;
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+ reverser.bind(transition);
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ }
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ )
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+};
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/footer_link2.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/footer_link2.gif
new file mode 100644
index 0000000..fa223b6
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/footer_link2.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/logo.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/logo.jpg
new file mode 100644
index 0000000..319bb51
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/logo.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/moo.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/moo.js
new file mode 100644
index 0000000..d70a1e4
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/moo.js
@@ -0,0 +1,133 @@
+/*
+moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
+by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
+for more info (http://moofx.mad4milk.net).
+Sunday, March 05, 2006
+v 1.2.3
+*/
+
+var fx = new Object();
+//base
+fx.Base = function(){};
+fx.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ duration: 500,
+ onComplete: '',
+ transition: fx.sinoidal
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ step: function() {
+ var time = (new Date).getTime();
+ if (time >= this.options.duration+this.startTime) {
+ this.now = this.to;
+ clearInterval (this.timer);
+ this.timer = null;
+ if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
+ }
+ else {
+ var Tpos = (time - this.startTime) / (this.options.duration);
+ this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
+ }
+ this.increase();
+ },
+
+ custom: function(from, to) {
+ if (this.timer != null) return;
+ this.from = from;
+ this.to = to;
+ this.startTime = (new Date).getTime();
+ this.timer = setInterval (this.step.bind(this), 13);
+ },
+
+ hide: function() {
+ this.now = 0;
+ this.increase();
+ },
+
+ clearTimer: function() {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+}
+
+//stretchers
+fx.Layout = Class.create();
+fx.Layout.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.el.style.overflow = "hidden";
+ this.iniWidth = this.el.offsetWidth;
+ this.iniHeight = this.el.offsetHeight;
+ this.setOptions(options);
+ }
+});
+
+fx.Height = Class.create();
+Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.height = this.now + "px";
+ },
+
+ toggle: function() {
+ if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
+ else this.custom(0, this.el.scrollHeight);
+ }
+});
+
+fx.Width = Class.create();
+Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {
+ increase: function() {
+ this.el.style.width = this.now + "px";
+ },
+
+ toggle: function(){
+ if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
+ else this.custom(0, this.iniWidth);
+ }
+});
+
+//fader
+fx.Opacity = Class.create();
+fx.Opacity.prototype = Object.extend(new fx.Base(), {
+ initialize: function(el, options) {
+ this.el = $(el);
+ this.now = 1;
+ this.increase();
+ this.setOptions(options);
+ },
+
+ increase: function() {
+ if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
+ this.setOpacity(this.now);
+ },
+
+ setOpacity: function(opacity) {
+ if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
+ else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
+ if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
+ this.el.style.opacity = opacity;
+ },
+
+ toggle: function() {
+ if (this.now > 0) this.custom(1, 0);
+ else this.custom(0, 1);
+ }
+});
+
+//transitions
+fx.sinoidal = function(pos){
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);
+ //this transition is from script.aculo.us
+}
+fx.linear = function(pos){
+ return pos;
+}
+fx.cubic = function(pos){
+ return Math.pow(pos, 3);
+}
+fx.circ = function(pos){
+ return Math.sqrt(pos);
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript.html b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript.html
new file mode 100644
index 0000000..813904e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>reCAPTCHA ????????????</title></head>
+<body><p>?????????????????????????????????????????????????????????? JavaScript?</p>
+<form action="" method="POST"><input name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="03AHJ_Vuvh5DqvT_pqg2eAbNkray1LmrDDBhyV0vS4Yhvs-nTq32iL3XOwJ6fYqNuC8iE59iyTLGk0afXRkDSs0gwhQsYN91uehs9DqkEysQeourr0VmRbzM2CQPSSijYfzFvcV67MVQgLwECGp_PC_UDMosfK0HUNEEmFK4E9QobK2JTpXDzuEZE" type="hidden">
+<center><img alt="" src="noscript_data/image.jpg" height="57" width="300"></center>
+<div class="recaptcha_input_area"><label for="recaptcha_response_field">????????</label></div>
+<div><input name="recaptcha_response_field" id="recaptcha_response_field" autocomplete="off" type="text"></div>
+<div><a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=false">???????</a>
+<a href="http://api.recaptcha.net/noscript?k=6LeHWwAAAAAAAC5Fs-j9puLX-bLoF6zF_i91c6Vq&amp;is_audio=true">????????</a>
+<a href="http://www.google.com/recaptcha/help?c=03AHJ_Vuvh5DqvT_pqg2eAbNkray1LmrDDBhyV0vS4Yhvs-nTq32iL3XOwJ6fYqNuC8iE59iyTLGk0afXRkDSs0gwhQsYN91uehs9DqkEysQeourr0VmRbzM2CQPSSijYfzFvcV67MVQgLwECGp_PC_UDMosfK0HUNEEmFK4E9QobK2JTpXDzuEZE&amp;hl=zh-CN" target="_blank">??</a></div>
+<div><input name="submit" value="????" type="submit"></div></form></body></html> \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript_data/image.jpg b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript_data/image.jpg
new file mode 100644
index 0000000..6167698
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/noscript_data/image.jpg
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype.js
new file mode 100644
index 0000000..69ae7f7
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype.js
@@ -0,0 +1,131 @@
+/* Prototype JavaScript framework
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://prototype.conio.net/
+/*--------------------------------------------------------------------------*/
+
+//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+Object.extend = function(destination, source) {
+ for (property in source) destination[property] = source[property];
+ return destination;
+}
+
+Function.prototype.bind = function(object) {
+ var __method = this;
+ return function() {
+ return __method.apply(object, arguments);
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+var __method = this;
+ return function(event) {
+ __method.call(object, event || window.event);
+ }
+}
+
+function $() {
+ if (arguments.length == 1) return get$(arguments[0]);
+ var elements = [];
+ $c(arguments).each(function(el){
+ elements.push(get$(el));
+ });
+ return elements;
+
+ function get$(el){
+ if (typeof el == 'string') el = document.getElementById(el);
+ return el;
+ }
+}
+
+if (!window.Element) var Element = new Object();
+
+Object.extend(Element, {
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ },
+
+ hasClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var hasClass = false;
+ element.className.split(' ').each(function(cn){
+ if (cn == className) hasClass = true;
+ });
+ return hasClass;
+ },
+
+ addClassName: function(element, className) {
+ element = $(element);
+ Element.removeClassName(element, className);
+ element.className += ' ' + className;
+ },
+
+ removeClassName: function(element, className) {
+ element = $(element);
+ if (!element) return;
+ var newClassName = '';
+ element.className.split(' ').each(function(cn, i){
+ if (cn != className){
+ if (i > 0) newClassName += ' ';
+ newClassName += cn;
+ }
+ });
+ element.className = newClassName;
+ },
+
+ cleanWhitespace: function(element) {
+ element = $(element);
+ $c(element.childNodes).each(function(node){
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
+ });
+ },
+
+ find: function(element, what) {
+ element = $(element)[what];
+ while (element.nodeType != 1) element = element[what];
+ return element;
+ }
+});
+
+var Position = {
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ }
+};
+
+document.getElementsByClassName = function(className) {
+ var children = document.getElementsByTagName('*') || document.all;
+ var elements = [];
+ $c(children).each(function(child){
+ if (Element.hasClassName(child, className)) elements.push(child);
+ });
+ return elements;
+}
+
+//useful array functions
+Array.prototype.each = function(func){
+ for(var i=0;ob=this[i];i++) func(ob, i);
+}
+
+function $c(array){
+ var nArray = [];
+ for (i=0;el=array[i];i++) nArray.push(el);
+ return nArray;
+} \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype_002.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype_002.js
new file mode 100644
index 0000000..2c70b8a
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/prototype_002.js
@@ -0,0 +1,4221 @@
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == originalAncestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/scriptaculous.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/scriptaculous.js
new file mode 100644
index 0000000..6cfe36e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/scriptaculous.js
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.1',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0',
+ load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+ }).each( function(s) {
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+}
+
+Scriptaculous.load(); \ No newline at end of file
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/slider.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/slider.js
new file mode 100644
index 0000000..cc46fe3
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/slider.js
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/sound.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/sound.js
new file mode 100644
index 0000000..eba3843
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/sound.js
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ })
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 }
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ else
+ Sound.play = function(){}
+}
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/swfobject.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/swfobject.js
new file mode 100644
index 0000000..9c6b79f
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/swfobject.js
@@ -0,0 +1,178 @@
+/**
+ * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
+ * legal reasons.
+ */
+if(typeof deconcept == "undefined") var deconcept = new Object();
+if(typeof deconcept.util == "undefined") deconcept.util = new Object();
+if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
+deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
+ if (!document.createElement || !document.getElementById) { return; }
+ this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
+ this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+ if(w) { this.setAttribute('width', w); }
+ if(h) { this.setAttribute('height', h); }
+ if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
+ this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
+ if(c) { this.addParam('bgcolor', c); }
+ var q = quality ? quality : 'high';
+ this.addParam('quality', q);
+ this.setAttribute('useExpressInstall', useExpressInstall);
+ this.setAttribute('doExpressInstall', false);
+ var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
+ this.setAttribute('xiRedirectUrl', xir);
+ this.setAttribute('redirectUrl', '');
+ if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
+}
+deconcept.SWFObject.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ write: function(elementId){
+ if(this.getAttribute('useExpressInstall')) {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
+ if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
+ this.setAttribute('doExpressInstall', true);
+ this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
+ document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+ this.addVariable("MMdoctitle", document.title);
+ }
+ }
+ if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+ return true;
+ }else{
+ if(this.getAttribute('redirectUrl') != "") {
+ document.location.replace(this.getAttribute('redirectUrl'));
+ }
+ }
+ return false;
+ }
+}
+
+/* ---- detection functions ---- */
+deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
+ var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else{
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ for (var i=3; axo!=null; i++) {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
+ PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
+ }
+ }catch(e){}
+ if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
+ // this only does the minor rev lookup if the user's major version
+ // is not 6 or we are checking for a specific minor or revision number
+ // see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
+ if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
+ try{
+ PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }catch(e){}
+ }
+ }
+ return PlayerVersion;
+}
+deconcept.PlayerVersion = function(arrVersion){
+ this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = parseInt(arrVersion[1]) || 0;
+ this.rev = parseInt(arrVersion[2]) || 0;
+}
+deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
+ if(this.major < fv.major) return false;
+ if(this.major > fv.major) return true;
+ if(this.minor < fv.minor) return false;
+ if(this.minor > fv.minor) return true;
+ if(this.rev < fv.rev) return false;
+ return true;
+}
+/* ---- get value of query string param ---- */
+deconcept.util = {
+ getRequestParameter: function(param){
+ var q = document.location.search || document.location.hash;
+ if(q){
+ var startIndex = q.indexOf(param +"=");
+ var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
+ if (q.length > 1 && startIndex > -1) {
+ return q.substring(q.indexOf("=", startIndex)+1, endIndex);
+ }
+ }
+ return "";
+ }
+}
+
+/* add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* add some aliases for ease of use/backwards compatibility */
+var getQueryParamValue = deconcept.util.getRequestParameter;
+var FlashObject = deconcept.SWFObject; // for legacy support
+var SWFObject = deconcept.SWFObject;
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu.js
new file mode 100644
index 0000000..5e70cf1
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu.js
@@ -0,0 +1,64 @@
+/*
+ UNU-specific JavaScript
+*/
+
+var UNU = {
+
+prepareNavigation:function()
+{
+ var lis = $('navul').childNodes;
+ for(var i=0;i<lis.length;i++)
+ {
+ // grab just the list items
+ if(lis[i].nodeType == 1 && lis[i].tagName.toLowerCase() == 'li')
+ {
+
+
+ current = lis[i].childNodes;
+ current[0].className = 'h';
+ el = current[0];
+ var wrapper = document.createElement('span');
+ el.parentNode.replaceChild(wrapper, el);
+ wrapper.appendChild(el);
+
+ var sub = lis[i].getElementsByTagName("ul");
+ if(sub.length > 0)
+ {
+ // attach a rollup effect and onclick event to the span inside the list item
+ // this element must be the first element (ie: no space between the open
+ // li and the <span> or <a>
+ lis[i].childNodes[0].fx = new fx.Height(sub[0], {duration:300});
+ lis[i].childNodes[0].fx.hide();
+ lis[i].childNodes[0].onclick = this.fxonclick;
+ }
+ }
+ }
+
+ var lis = $('navul').getElementsByTagName('li');
+ for(var i=0;i<lis.length;i++)
+ {
+ if(lis[i].className && lis[i].className.match(/current_page_item/))
+ {
+
+ if(lis[i].childNodes[0].fx)
+ {
+
+
+ lis[i].childNodes[0].fx.toggle();
+ }else if(lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx){
+ lis[i].parentNode.parentNode.parentNode.parentNode.childNodes[0].fx.toggle();
+ } else if(lis[i].parentNode.parentNode.childNodes[0].fx){
+
+
+ lis[i].parentNode.parentNode.childNodes[0].fx.toggle();
+ }
+ }
+ }
+},
+
+fxonclick:function(){
+ this.fx.toggle();
+ return false;
+}
+
+};
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu_logo_white.gif b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu_logo_white.gif
new file mode 100644
index 0000000..14f1c4e
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/unu_logo_white.gif
Binary files differ
diff --git a/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/urchin.js b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/urchin.js
new file mode 100644
index 0000000..3913c02
--- /dev/null
+++ b/assignment1/materials/Environmental Impact Assessment Course Module » 2-6 Summary_files/urchin.js
@@ -0,0 +1,695 @@
+//-- Google Analytics Urchin Module
+//-- Copyright 2007 Google, All Rights Reserved.
+
+//-- Urchin On Demand Settings ONLY
+var _uacct=""; // set up the Urchin Account
+var _userv=1; // service mode (0=local,1=remote,2=both)
+
+//-- UTM User Settings
+var _ufsc=1; // set client info flag (1=on|0=off)
+var _udn="auto"; // (auto|none|domain) set the domain name for cookies
+var _uhash="on"; // (on|off) unique domain hash for cookies
+var _utimeout="1800"; // set the inactive session timeout in seconds
+var _ugifpath="/__utm.gif"; // set the web path to the __utm.gif file
+var _utsp="|"; // transaction field separator
+var _uflash=1; // set flash version detect option (1=on|0=off)
+var _utitle=1; // set the document title detect option (1=on|0=off)
+var _ulink=0; // enable linker functionality (1=on|0=off)
+var _uanchor=0; // enable use of anchors for campaign (1=on|0=off)
+var _utcp="/"; // the cookie path for tracking
+var _usample=100; // The sampling % of visitors to track (1-100).
+
+//-- UTM Campaign Tracking Settings
+var _uctm=1; // set campaign tracking module (1=on|0=off)
+var _ucto="15768000"; // set timeout in seconds (6 month default)
+var _uccn="utm_campaign"; // name
+var _ucmd="utm_medium"; // medium (cpc|cpm|link|email|organic)
+var _ucsr="utm_source"; // source
+var _uctr="utm_term"; // term/keyword
+var _ucct="utm_content"; // content
+var _ucid="utm_id"; // id number
+var _ucno="utm_nooverride"; // don't override
+
+//-- Auto/Organic Sources and Keywords
+var _uOsr=new Array();
+var _uOkw=new Array();
+_uOsr[0]="google"; _uOkw[0]="q";
+_uOsr[1]="yahoo"; _uOkw[1]="p";
+_uOsr[2]="msn"; _uOkw[2]="q";
+_uOsr[3]="aol"; _uOkw[3]="query";
+_uOsr[4]="aol"; _uOkw[4]="encquery";
+_uOsr[5]="lycos"; _uOkw[5]="query";
+_uOsr[6]="ask"; _uOkw[6]="q";
+_uOsr[7]="altavista"; _uOkw[7]="q";
+_uOsr[8]="netscape"; _uOkw[8]="query";
+_uOsr[9]="cnn"; _uOkw[9]="query";
+_uOsr[10]="looksmart"; _uOkw[10]="qt";
+_uOsr[11]="about"; _uOkw[11]="terms";
+_uOsr[12]="mamma"; _uOkw[12]="query";
+_uOsr[13]="alltheweb"; _uOkw[13]="q";
+_uOsr[14]="gigablast"; _uOkw[14]="q";
+_uOsr[15]="voila"; _uOkw[15]="rdata";
+_uOsr[16]="virgilio"; _uOkw[16]="qs";
+_uOsr[17]="live"; _uOkw[17]="q";
+_uOsr[18]="baidu"; _uOkw[18]="wd";
+_uOsr[19]="alice"; _uOkw[19]="qs";
+_uOsr[20]="yandex"; _uOkw[20]="text";
+_uOsr[21]="najdi"; _uOkw[21]="q";
+_uOsr[22]="aol"; _uOkw[22]="q";
+_uOsr[23]="club-internet"; _uOkw[23]="query";
+_uOsr[24]="mama"; _uOkw[24]="query";
+_uOsr[25]="seznam"; _uOkw[25]="q";
+_uOsr[26]="search"; _uOkw[26]="q";
+_uOsr[27]="wp"; _uOkw[27]="szukaj";
+_uOsr[28]="onet"; _uOkw[28]="qt";
+_uOsr[29]="netsprint"; _uOkw[29]="q";
+_uOsr[30]="google.interia"; _uOkw[30]="q";
+_uOsr[31]="szukacz"; _uOkw[31]="q";
+_uOsr[32]="yam"; _uOkw[32]="k";
+_uOsr[33]="pchome"; _uOkw[33]="q";
+_uOsr[34]="kvasir"; _uOkw[34]="searchExpr";
+_uOsr[35]="sesam"; _uOkw[35]="q";
+_uOsr[36]="ozu"; _uOkw[36]="q";
+_uOsr[37]="terra"; _uOkw[37]="query";
+_uOsr[38]="nostrum"; _uOkw[38]="query";
+_uOsr[39]="mynet"; _uOkw[39]="q";
+_uOsr[40]="ekolay"; _uOkw[40]="q";
+_uOsr[41]="search.ilse"; _uOkw[41]="search_for";
+_uOsr[42]="bing"; _uOkw[42]="q";
+
+//-- Auto/Organic Keywords to Ignore
+var _uOno=new Array();
+//_uOno[0]="urchin";
+//_uOno[1]="urchin.com";
+//_uOno[2]="www.urchin.com";
+
+//-- Referral domains to Ignore
+var _uRno=new Array();
+//_uRno[0]=".urchin.com";
+
+//-- **** Don't modify below this point ***
+var _uff,_udh,_udt,_ubl=0,_udo="",_uu,_ufns=0,_uns=0,_ur="-",_ufno=0,_ust=0,_ubd=document,_udl=_ubd.location,_udlh="",_uwv="1.4";
+var _ugifpath2="http://www.google-analytics.com/__utm.gif";
+if (_udl.hash) _udlh=_udl.href.substring(_udl.href.indexOf('#'));
+if (_udl.protocol=="https:") _ugifpath2="https://ssl.google-analytics.com/__utm.gif";
+if (!_utcp || _utcp=="") _utcp="/";
+function urchinTracker(page) {
+ if (_udl.protocol=="file:") return;
+ if (_uff && (!page || page=="")) return;
+ var a,b,c,xx,v,z,k,x="",s="",f=0,nv=0;
+ var nx=" expires="+_uNx()+";";
+ var dc=_ubd.cookie;
+ _udh=_uDomain();
+ if (!_uVG()) return;
+ _uu=Math.round(Math.random()*2147483647);
+ _udt=new Date();
+ _ust=Math.round(_udt.getTime()/1000);
+ a=dc.indexOf("__utma="+_udh+".");
+ b=dc.indexOf("__utmb="+_udh);
+ c=dc.indexOf("__utmc="+_udh);
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ if (_utimeout && _utimeout!="") {
+ x=new Date(_udt.getTime()+(_utimeout*1000));
+ x=" expires="+x.toGMTString()+";";
+ }
+ if (_ulink) {
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ if(s && s!="" && s.indexOf("__utma=")>=0) {
+ if (!(_uIN(a=_uGC(s,"__utma=","&")))) a="-";
+ if (!(_uIN(b=_uGC(s,"__utmb=","&")))) b="-";
+ if (!(_uIN(c=_uGC(s,"__utmc=","&")))) c="-";
+ v=_uGC(s,"__utmv=","&");
+ z=_uGC(s,"__utmz=","&");
+ k=_uGC(s,"__utmk=","&");
+ xx=_uGC(s,"__utmx=","&");
+ if ((k*1) != ((_uHash(a+b+c+xx+z+v)*1)+(_udh*1))) {_ubl=1;a="-";b="-";c="-";xx="-";z="-";v="-";}
+ if (a!="-" && b!="-" && c!="-") f=1;
+ else if(a!="-") f=2;
+ }
+ }
+ if(f==1) {
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+c+"; path="+_utcp+";"+_udo;
+ } else if (f==2) {
+ a=_uFixA(s,"&",_ust);
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ } else if (a>=0 && b>=0 && c>=0) {
+ b = _uGC(dc,"__utmb="+_udh,";");
+ b = ("-" == b) ? _udh : b;
+ _ubd.cookie="__utmb="+b+"; path="+_utcp+";"+x+_udo;
+ } else {
+ if (a>=0) a=_uFixA(_ubd.cookie,";",_ust);
+ else {
+ a=_udh+"."+_uu+"."+_ust+"."+_ust+"."+_ust+".1";
+ nv=1;
+ }
+ _ubd.cookie="__utma="+a+"; path="+_utcp+";"+nx+_udo;
+ _ubd.cookie="__utmb="+_udh+"; path="+_utcp+";"+x+_udo;
+ _ubd.cookie="__utmc="+_udh+"; path="+_utcp+";"+_udo;
+ _ufns=1;
+ }
+ if (_ulink && xx && xx!="" && xx!="-") {
+ xx=_uUES(xx);
+ if (xx.indexOf(";")==-1) _ubd.cookie="__utmx="+xx+"; path="+_utcp+";"+nx+_udo;
+ }
+ if (_ulink && v && v!="" && v!="-") {
+ v=_uUES(v);
+ if (v.indexOf(";")==-1) _ubd.cookie="__utmv="+v+"; path="+_utcp+";"+nx+_udo;
+ }
+ var wc=window;
+ var c=_ubd.cookie;
+ if(wc && wc.gaGlobal && wc.gaGlobal.dh==_udh){
+ var g=wc.gaGlobal;
+ var ua=c.split("__utma="+_udh+".")[1].split(";")[0].split(".");
+ if(g.sid)ua[3]=g.sid;
+ if(nv>0){
+ ua[2]=ua[3];
+ if(g.vid){
+ var v=g.vid.split(".");
+ ua[0]=v[0];
+ ua[1]=v[1];
+ }
+ }
+ _ubd.cookie="__utma="+_udh+"."+ua.join(".")+"; path="+_utcp+";"+nx+_udo;
+ }
+ _uInfo(page);
+ _ufns=0;
+ _ufno=0;
+ if (!page || page=="") _uff=1;
+}
+function _uGH() {
+ var hid;
+ var wc=window;
+ if (wc && wc.gaGlobal && wc.gaGlobal.hid) {
+ hid=wc.gaGlobal.hid;
+ } else {
+ hid=Math.round(Math.random()*0x7fffffff);
+ if (!wc.gaGlobal) wc.gaGlobal={};
+ wc.gaGlobal.hid=hid;
+ }
+ return hid;
+}
+function _uInfo(page) {
+ var p,s="",dm="",pg=_udl.pathname+_udl.search;
+ if (page && page!="") pg=_uES(page,1);
+ _ur=_ubd.referrer;
+ if (!_ur || _ur=="") { _ur="-"; }
+ else {
+ dm=_ubd.domain;
+ if(_utcp && _utcp!="/") dm+=_utcp;
+ p=_ur.indexOf(dm);
+ if ((p>=0) && (p<=8)) { _ur="0"; }
+ if (_ur.indexOf("[")==0 && _ur.lastIndexOf("]")==(_ur.length-1)) { _ur="-"; }
+ }
+ s+="&utmn="+_uu;
+ if (_ufsc) s+=_uBInfo();
+ if (_uctm) s+=_uCInfo();
+ if (_utitle && _ubd.title && _ubd.title!="") s+="&utmdt="+_uES(_ubd.title);
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ s+="&utmhid="+_uGH();
+ s+="&utmr="+_ur;
+ s+="&utmp="+pg;
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+ return;
+}
+function _uVoid() { return; }
+function _uCInfo() {
+ if (!_ucto || _ucto=="") { _ucto="15768000"; }
+ if (!_uVG()) return;
+ var c="",t="-",t2="-",t3="-",o=0,cs=0,cn=0,i=0,z="-",s="";
+ if (_uanchor && _udlh && _udlh!="") s=_udlh+"&";
+ s+=_udl.search;
+ var x=new Date(_udt.getTime()+(_ucto*1000));
+ var dc=_ubd.cookie;
+ x=" expires="+x.toGMTString()+";";
+ if (_ulink && !_ubl) {
+ z=_uUES(_uGC(s,"__utmz=","&"));
+ if (z!="-" && z.indexOf(";")==-1) { _ubd.cookie="__utmz="+z+"; path="+_utcp+";"+x+_udo; return ""; }
+ }
+ z=dc.indexOf("__utmz="+_udh+".");
+ if (z>-1) { z=_uGC(dc,"__utmz="+_udh+".",";"); }
+ else { z="-"; }
+ t=_uGC(s,_ucid+"=","&");
+ t2=_uGC(s,_ucsr+"=","&");
+ t3=_uGC(s,"gclid=","&");
+ if ((t!="-" && t!="") || (t2!="-" && t2!="") || (t3!="-" && t3!="")) {
+ if (t!="-" && t!="") c+="utmcid="+_uEC(t);
+ if (t2!="-" && t2!="") { if (c != "") c+="|"; c+="utmcsr="+_uEC(t2); }
+ if (t3!="-" && t3!="") { if (c != "") c+="|"; c+="utmgclid="+_uEC(t3); }
+ t=_uGC(s,_uccn+"=","&");
+ if (t!="-" && t!="") c+="|utmccn="+_uEC(t);
+ else c+="|utmccn=(not+set)";
+ t=_uGC(s,_ucmd+"=","&");
+ if (t!="-" && t!="") c+="|utmcmd="+_uEC(t);
+ else c+="|utmcmd=(not+set)";
+ t=_uGC(s,_uctr+"=","&");
+ if (t!="-" && t!="") c+="|utmctr="+_uEC(t);
+ else { t=_uOrg(1); if (t!="-" && t!="") c+="|utmctr="+_uEC(t); }
+ t=_uGC(s,_ucct+"=","&");
+ if (t!="-" && t!="") c+="|utmcct="+_uEC(t);
+ t=_uGC(s,_ucno+"=","&");
+ if (t=="1") o=1;
+ if (z!="-" && o==1) return "";
+ }
+ if (c=="-" || c=="") { c=_uOrg(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") { if (_ufns==1) c=_uRef(); if (z!="-" && _ufno==1) return ""; }
+ if (c=="-" || c=="") {
+ if (z=="-" && _ufns==1) { c="utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)"; }
+ if (c=="-" || c=="") return "";
+ }
+ if (z!="-") {
+ i=z.indexOf(".");
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ if (i>-1) i=z.indexOf(".",i+1);
+ t=z.substring(i+1,z.length);
+ if (t.toLowerCase()==c.toLowerCase()) cs=1;
+ t=z.substring(0,i);
+ if ((i=t.lastIndexOf(".")) > -1) {
+ t=t.substring(i+1,t.length);
+ cn=(t*1);
+ }
+ }
+ if (cs==0 || _ufns==1) {
+ t=_uGC(dc,"__utma="+_udh+".",";");
+ if ((i=t.lastIndexOf(".")) > 9) {
+ _uns=t.substring(i+1,t.length);
+ _uns=(_uns*1);
+ }
+ cn++;
+ if (_uns==0) _uns=1;
+ _ubd.cookie="__utmz="+_udh+"."+_ust+"."+_uns+"."+cn+"."+c+"; path="+_utcp+"; "+x+_udo;
+ }
+ if (cs==0 || _ufns==1) return "&utmcn=1";
+ else return "&utmcr=1";
+}
+function _uRef() {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k,n;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ k=h.substring(h.indexOf("/"),h.length);
+ if (k.indexOf("?") > -1) k=k.substring(0,k.indexOf("?"));
+ h=h.substring(0,h.indexOf("/"));
+ }
+ h=h.toLowerCase();
+ n=h;
+ if ((i=n.indexOf(":")) > -1) n=n.substring(0,i);
+ for (var ii=0;ii<_uRno.length;ii++) {
+ if ((i=n.indexOf(_uRno[ii].toLowerCase())) > -1 && n.length==(i+_uRno[ii].length)) { _ufno=1; break; }
+ }
+ if (h.indexOf("www.")==0) h=h.substring(4,h.length);
+ return "utmccn=(referral)|utmcsr="+_uEC(h)+"|"+"utmcct="+_uEC(k)+"|utmcmd=referral";
+}
+function _uOrg(t) {
+ if (_ur=="0" || _ur=="" || _ur=="-") return "";
+ var i=0,h,k;
+ if ((i=_ur.indexOf("://"))<0 || _uGCse()) return "";
+ h=_ur.substring(i+3,_ur.length);
+ if (h.indexOf("/") > -1) {
+ h=h.substring(0,h.indexOf("/"));
+ }
+ for (var ii=0;ii<_uOsr.length;ii++) {
+ if (h.toLowerCase().indexOf(_uOsr[ii].toLowerCase()) > -1) {
+ if ((i=_ur.indexOf("?"+_uOkw[ii]+"=")) > -1 || (i=_ur.indexOf("&"+_uOkw[ii]+"=")) > -1) {
+ k=_ur.substring(i+_uOkw[ii].length+2,_ur.length);
+ if ((i=k.indexOf("&")) > -1) k=k.substring(0,i);
+ for (var yy=0;yy<_uOno.length;yy++) {
+ if (_uOno[yy].toLowerCase()==k.toLowerCase()) { _ufno=1; break; }
+ }
+ if (t) return _uEC(k);
+ else return "utmccn=(organic)|utmcsr="+_uEC(_uOsr[ii])+"|"+"utmctr="+_uEC(k)+"|utmcmd=organic";
+ }
+ }
+ }
+ return "";
+}
+function _uGCse() {
+ var h,p;
+ h=p=_ur.split("://")[1];
+ if(h.indexOf("/")>-1) {
+ h=h.split("/")[0];
+ p=p.substring(p.indexOf("/")+1,p.length);
+ }
+ if(p.indexOf("?")>-1) {
+ p=p.split("?")[0];
+ }
+ if(h.toLowerCase().indexOf("google")>-1) {
+ if(_ur.indexOf("?q=")>-1 || _ur.indexOf("&q=")>-1) {
+ if (p.toLowerCase().indexOf("cse")>-1) {
+ return true;
+ }
+ }
+ }
+}
+function _uBInfo() {
+ var sr="-",sc="-",ul="-",fl="-",cs="-",je=1;
+ var n=navigator;
+ if (self.screen) {
+ sr=screen.width+"x"+screen.height;
+ sc=screen.colorDepth+"-bit";
+ } else if (self.java) {
+ var j=java.awt.Toolkit.getDefaultToolkit();
+ var s=j.getScreenSize();
+ sr=s.width+"x"+s.height;
+ }
+ if (n.language) { ul=n.language.toLowerCase(); }
+ else if (n.browserLanguage) { ul=n.browserLanguage.toLowerCase(); }
+ je=n.javaEnabled()?1:0;
+ if (_uflash) fl=_uFlash();
+ if (_ubd.characterSet) cs=_uES(_ubd.characterSet);
+ else if (_ubd.charset) cs=_uES(_ubd.charset);
+ return "&utmcs="+cs+"&utmsr="+sr+"&utmsc="+sc+"&utmul="+ul+"&utmje="+je+"&utmfl="+fl;
+}
+function __utmSetTrans() {
+ var e;
+ if (_ubd.getElementById) e=_ubd.getElementById("utmtrans");
+ else if (_ubd.utmform && _ubd.utmform.utmtrans) e=_ubd.utmform.utmtrans;
+ if (!e) return;
+ var l=e.value.split("UTM:");
+ var i,i2,c;
+ if (_userv==0 || _userv==2) i=new Array();
+ if (_userv==1 || _userv==2) { i2=new Array(); c=_uGCS(); }
+
+ for (var ii=0;ii<l.length;ii++) {
+ l[ii]=_uTrim(l[ii]);
+ if (l[ii].charAt(0)!='T' && l[ii].charAt(0)!='I') continue;
+ var r=Math.round(Math.random()*2147483647);
+ if (!_utsp || _utsp=="") _utsp="|";
+ var f=l[ii].split(_utsp),s="";
+ if (f[0].charAt(0)=='T') {
+ s="&utmt=tran"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmtst="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmtto="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmttx="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmtsp="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmtci="+_uES(f[6]);
+ f[7]=_uTrim(f[7]); if(f[7]&&f[7]!="") s+="&utmtrg="+_uES(f[7]);
+ f[8]=_uTrim(f[8]); if(f[8]&&f[8]!="") s+="&utmtco="+_uES(f[8]);
+ } else {
+ s="&utmt=item"+"&utmn="+r;
+ f[1]=_uTrim(f[1]); if(f[1]&&f[1]!="") s+="&utmtid="+_uES(f[1]);
+ f[2]=_uTrim(f[2]); if(f[2]&&f[2]!="") s+="&utmipc="+_uES(f[2]);
+ f[3]=_uTrim(f[3]); if(f[3]&&f[3]!="") s+="&utmipn="+_uES(f[3]);
+ f[4]=_uTrim(f[4]); if(f[4]&&f[4]!="") s+="&utmiva="+_uES(f[4]);
+ f[5]=_uTrim(f[5]); if(f[5]&&f[5]!="") s+="&utmipr="+_uES(f[5]);
+ f[6]=_uTrim(f[6]); if(f[6]&&f[6]!="") s+="&utmiqt="+_uES(f[6]);
+ }
+ if (_udl.hostname && _udl.hostname!="") s+="&utmhn="+_uES(_udl.hostname);
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ i[ii]=new Image(1,1);
+ i[ii].src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i[ii].onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ i2[ii]=new Image(1,1);
+ i2[ii].src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+c;
+ i2[ii].onload=function() { _uVoid(); }
+ }
+ }
+ return;
+}
+function _uFlash() {
+ var f="-",n=navigator;
+ if (n.plugins && n.plugins.length) {
+ for (var ii=0;ii<n.plugins.length;ii++) {
+ if (n.plugins[ii].name.indexOf('Shockwave Flash')!=-1) {
+ f=n.plugins[ii].description.split('Shockwave Flash ')[1];
+ break;
+ }
+ }
+ } else {
+ var fl;
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ f = "WIN 6,0,21,0";
+ fl.AllowScriptAccess = "always";
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f == "-") {
+ try {
+ fl = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ f = fl.GetVariable("$version");
+ } catch(e) {}
+ }
+ if (f != "-") {
+ f = f.split(" ")[1].split(",");
+ f = f[0] + "." + f[1] + " r" + f[2];
+ }
+ }
+ return f;
+}
+function __utmLinkerUrl(l,h) {
+ var p,k,a="-",b="-",c="-",x="-",z="-",v="-";
+ var dc=_ubd.cookie;
+ var iq = l.indexOf("?");
+ var ih = l.indexOf("#");
+ var url=l;
+ if (dc) {
+ a=_uES(_uGC(dc,"__utma="+_udh+".",";"));
+ b=_uES(_uGC(dc,"__utmb="+_udh,";"));
+ c=_uES(_uGC(dc,"__utmc="+_udh,";"));
+ x=_uES(_uGC(dc,"__utmx="+_udh,";"));
+ z=_uES(_uGC(dc,"__utmz="+_udh+".",";"));
+ v=_uES(_uGC(dc,"__utmv="+_udh+".",";"));
+ k=(_uHash(a+b+c+x+z+v)*1)+(_udh*1);
+ p="__utma="+a+"&__utmb="+b+"&__utmc="+c+"&__utmx="+x+"&__utmz="+z+"&__utmv="+v+"&__utmk="+k;
+ }
+ if (p) {
+ if (h && ih>-1) return;
+ if (h) { url=l+"#"+p; }
+ else {
+ if (iq==-1 && ih==-1) url=l+"?"+p;
+ else if (ih==-1) url=l+"&"+p;
+ else if (iq==-1) url=l.substring(0,ih-1)+"?"+p+l.substring(ih);
+ else url=l.substring(0,ih-1)+"&"+p+l.substring(ih);
+ }
+ }
+ return url;
+}
+function __utmLinker(l,h) {
+ if (!_ulink || !l || l=="") return;
+ _udl.href=__utmLinkerUrl(l,h);
+}
+function __utmLinkPost(f,h) {
+ if (!_ulink || !f || !f.action) return;
+ f.action=__utmLinkerUrl(f.action, h);
+ return;
+}
+function __utmSetVar(v) {
+ if (!v || v=="") return;
+ if (!_udo || _udo == "") {
+ _udh=_uDomain();
+ if (_udn && _udn!="") { _udo=" domain="+_udn+";"; }
+ }
+ if (!_uVG()) return;
+ var r=Math.round(Math.random() * 2147483647);
+ _ubd.cookie="__utmv="+_udh+"."+_uES(v)+"; path="+_utcp+"; expires="+_uNx()+";"+_udo;
+ var s="&utmt=var&utmn="+r;
+ if (_usample && _usample != 100) s+="&utmsp="+_uES(_usample);
+ if ((_userv==0 || _userv==2) && _uSP()) {
+ var i=new Image(1,1);
+ i.src=_ugifpath+"?"+"utmwv="+_uwv+s;
+ i.onload=function() { _uVoid(); }
+ }
+ if ((_userv==1 || _userv==2) && _uSP()) {
+ var i2=new Image(1,1);
+ i2.src=_ugifpath2+"?"+"utmwv="+_uwv+s+"&utmac="+_uacct+"&utmcc="+_uGCS();
+ i2.onload=function() { _uVoid(); }
+ }
+}
+function _uGCS() {
+ var t,c="",dc=_ubd.cookie;
+ if ((t=_uGC(dc,"__utma="+_udh+".",";"))!="-") c+=_uES("__utma="+t+";+");
+ if ((t=_uGC(dc,"__utmx="+_udh,";"))!="-") c+=_uES("__utmx="+t+";+");
+ if ((t=_uGC(dc,"__utmz="+_udh+".",";"))!="-") c+=_uES("__utmz="+t+";+");
+ if ((t=_uGC(dc,"__utmv="+_udh+".",";"))!="-") c+=_uES("__utmv="+t+";");
+ if (c.charAt(c.length-1)=="+") c=c.substring(0,c.length-1);
+ return c;
+}
+function _uGC(l,n,s) {
+ if (!l || l=="" || !n || n=="" || !s || s=="") return "-";
+ var i,i2,i3,c="-";
+ i=l.indexOf(n);
+ i3=n.indexOf("=")+1;
+ if (i > -1) {
+ i2=l.indexOf(s,i); if (i2 < 0) { i2=l.length; }
+ c=l.substring((i+i3),i2);
+ }
+ return c;
+}
+function _uDomain() {
+ if (!_udn || _udn=="" || _udn=="none") { _udn=""; return 1; }
+ if (_udn=="auto") {
+ var d=_ubd.domain;
+ if (d.substring(0,4)=="www.") {
+ d=d.substring(4,d.length);
+ }
+ _udn=d;
+ }
+ _udn = _udn.toLowerCase();
+ if (_uhash=="off") return 1;
+ return _uHash(_udn);
+}
+function _uHash(d) {
+ if (!d || d=="") return 1;
+ var h=0,g=0;
+ for (var i=d.length-1;i>=0;i--) {
+ var c=parseInt(d.charCodeAt(i));
+ h=((h << 6) & 0xfffffff) + c + (c << 14);
+ if ((g=h & 0xfe00000)!=0) h=(h ^ (g >> 21));
+ }
+ return h;
+}
+function _uFixA(c,s,t) {
+ if (!c || c=="" || !s || s=="" || !t || t=="") return "-";
+ var a=_uGC(c,"__utma="+_udh+".",s);
+ var lt=0,i=0;
+ if ((i=a.lastIndexOf(".")) > 9) {
+ _uns=a.substring(i+1,a.length);
+ _uns=(_uns*1)+1;
+ a=a.substring(0,i);
+ if ((i=a.lastIndexOf(".")) > 7) {
+ lt=a.substring(i+1,a.length);
+ a=a.substring(0,i);
+ }
+ if ((i=a.lastIndexOf(".")) > 5) {
+ a=a.substring(0,i);
+ }
+ a+="."+lt+"."+t+"."+_uns;
+ }
+ return a;
+}
+function _uTrim(s) {
+ if (!s || s=="") return "";
+ while ((s.charAt(0)==' ') || (s.charAt(0)=='\n') || (s.charAt(0,1)=='\r')) s=s.substring(1,s.length);
+ while ((s.charAt(s.length-1)==' ') || (s.charAt(s.length-1)=='\n') || (s.charAt(s.length-1)=='\r')) s=s.substring(0,s.length-1);
+ return s;
+}
+function _uEC(s) {
+ var n="";
+ if (!s || s=="") return "";
+ for (var i=0;i<s.length;i++) {if (s.charAt(i)==" ") n+="+"; else n+=s.charAt(i);}
+ return n;
+}
+function __utmVisitorCode(f) {
+ var r=0,t=0,i=0,i2=0,m=31;
+ var a=_uGC(_ubd.cookie,"__utma="+_udh+".",";");
+ if ((i=a.indexOf(".",0))<0) return;
+ if ((i2=a.indexOf(".",i+1))>0) r=a.substring(i+1,i2); else return "";
+ if ((i=a.indexOf(".",i2+1))>0) t=a.substring(i2+1,i); else return "";
+ if (f) {
+ return r;
+ } else {
+ var c=new Array('A','B','C','D','E','F','G','H','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9');
+ return c[r>>28&m]+c[r>>23&m]+c[r>>18&m]+c[r>>13&m]+"-"+c[r>>8&m]+c[r>>3&m]+c[((r&7)<<2)+(t>>30&3)]+c[t>>25&m]+c[t>>20&m]+"-"+c[t>>15&m]+c[t>>10&m]+c[t>>5&m]+c[t&m];
+ }
+}
+function _uIN(n) {
+ if (!n) return false;
+ for (var i=0;i<n.length;i++) {
+ var c=n.charAt(i);
+ if ((c<"0" || c>"9") && (c!=".")) return false;
+ }
+ return true;
+}
+function _uES(s,u) {
+ if (typeof(encodeURIComponent) == 'function') {
+ if (u) return encodeURI(s);
+ else return encodeURIComponent(s);
+ } else {
+ return escape(s);
+ }
+}
+function _uUES(s) {
+ if (typeof(decodeURIComponent) == 'function') {
+ return decodeURIComponent(s);
+ } else {
+ return unescape(s);
+ }
+}
+function _uVG() {
+ if((_udn.indexOf("www.google.") == 0 || _udn.indexOf(".google.") == 0 || _udn.indexOf("google.") == 0) && _utcp=='/' && _udn.indexOf("google.org")==-1) {
+ return false;
+ }
+ return true;
+}
+function _uSP() {
+ var s=100;
+ if (_usample) s=_usample;
+ if(s>=100 || s<=0) return true;
+ return ((__utmVisitorCode(1)%10000)<(s*100));
+}
+function urchinPathCopy(p){
+ var d=document,nx,tx,sx,i,c,cs,t,h,o;
+ cs=new Array("a","b","c","v","x","z");
+ h=_uDomain(); if (_udn && _udn!="") o=" domain="+_udn+";";
+ nx=_uNx()+";";
+ tx=new Date(); tx.setTime(tx.getTime()+(_utimeout*1000));
+ tx=tx.toGMTString()+";";
+ sx=new Date(); sx.setTime(sx.getTime()+(_ucto*1000));
+ sx=sx.toGMTString()+";";
+ for (i=0;i<6;i++){
+ t=" expires=";
+ if (i==1) t+=tx; else if (i==2) t=""; else if (i==5) t+=sx; else t+=nx;
+ c=_uGC(d.cookie,"__utm"+cs[i]+"="+h,";");
+ if (c!="-") d.cookie="__utm"+cs[i]+"="+c+"; path="+p+";"+t+o;
+ }
+}
+function _uCO() {
+ if (!_utk || _utk=="" || _utk.length<10) return;
+ var d='www.google.com';
+ if (_utk.charAt(0)=='!') d='analytics.corp.google.com';
+ _ubd.cookie="GASO="+_utk+"; path="+_utcp+";"+_udo;
+ var sc=document.createElement('script');
+ sc.type='text/javascript';
+ sc.id="_gasojs";
+ sc.src='https://'+d+'/analytics/reporting/overlay_js?gaso='+_utk+'&'+Math.random();
+ document.getElementsByTagName('head')[0].appendChild(sc);
+}
+function _uGT() {
+ var h=location.hash, a;
+ if (h && h!="" && h.indexOf("#gaso=")==0) {
+ a=_uGC(h,"gaso=","&");
+ } else {
+ a=_uGC(_ubd.cookie,"GASO=",";");
+ }
+ return a;
+}
+var _utk=_uGT();
+if (_utk && _utk!="" && _utk.length>10 && _utk.indexOf("=")==-1) {
+ if (window.addEventListener) {
+ window.addEventListener('load', _uCO, false);
+ } else if (window.attachEvent) {
+ window.attachEvent('onload', _uCO);
+ }
+}
+
+function _uNx() {
+ return (new Date((new Date()).getTime()+63072000000)).toGMTString();
+}
diff --git a/assignment1/materials/Green Book_Environmental Methods Review.pdf b/assignment1/materials/Green Book_Environmental Methods Review.pdf
new file mode 100644
index 0000000..bcbb137
--- /dev/null
+++ b/assignment1/materials/Green Book_Environmental Methods Review.pdf
Binary files differ
diff --git a/assignment1/materials/RMA/key-facts-2010-11.pdf b/assignment1/materials/RMA/key-facts-2010-11.pdf
new file mode 100644
index 0000000..5957032
--- /dev/null
+++ b/assignment1/materials/RMA/key-facts-2010-11.pdf
Binary files differ
diff --git a/assignment1/materials/RMA/resource-consent-analysis-nov06.pdf b/assignment1/materials/RMA/resource-consent-analysis-nov06.pdf
new file mode 100644
index 0000000..dd315a2
--- /dev/null
+++ b/assignment1/materials/RMA/resource-consent-analysis-nov06.pdf
Binary files differ
diff --git a/assignment1/materials/RMA/rma-guide-aug06.pdf b/assignment1/materials/RMA/rma-guide-aug06.pdf
new file mode 100644
index 0000000..b0162ca
--- /dev/null
+++ b/assignment1/materials/RMA/rma-guide-aug06.pdf
Binary files differ
diff --git a/assignment1/materials/SEA/SEA-comparison-scotland-new-zealand.pdf b/assignment1/materials/SEA/SEA-comparison-scotland-new-zealand.pdf
new file mode 100644
index 0000000..1b0db07
--- /dev/null
+++ b/assignment1/materials/SEA/SEA-comparison-scotland-new-zealand.pdf
Binary files differ
diff --git a/assignment1/materials/SEA/SEAPolicyLevel_MoECzech_2005.pdf b/assignment1/materials/SEA/SEAPolicyLevel_MoECzech_2005.pdf
new file mode 100644
index 0000000..cdabbe7
--- /dev/null
+++ b/assignment1/materials/SEA/SEAPolicyLevel_MoECzech_2005.pdf
Binary files differ
diff --git a/assignment1/materials/SEA/review-of-SEA-in-12-countries.pdf b/assignment1/materials/SEA/review-of-SEA-in-12-countries.pdf
new file mode 100644
index 0000000..0b97f51
--- /dev/null
+++ b/assignment1/materials/SEA/review-of-SEA-in-12-countries.pdf
Binary files differ
diff --git a/assignment1/materials/devolution.pdf b/assignment1/materials/devolution.pdf
new file mode 100644
index 0000000..d3118d6
--- /dev/null
+++ b/assignment1/materials/devolution.pdf
@@ -0,0 +1,17059 @@
+%PDF-1.2 %
+1 0 obj << /Type /Page /Parent 123 0 R /Resources 119 0 R /Contents 118 0 R >> endobj 3 0 obj << /Title (ABSTRACT) /Dest [ 1 0 R /FitH 468 ] /Parent 305 0 R /Next 5 0 R >> endobj 4 0 obj << /Type /Page /Parent 123 0 R /Resources 134 0 R /Contents 133 0 R >> endobj 5 0 obj << /Title (EXECUTIVE SUMMARY) /Dest [ 4 0 R /FitH 757 ] /Parent 305 0 R /Prev 3 0 R /Next 19 0 R /Count 0 >> endobj 7 0 obj << /Type /Page /Parent 123 0 R /Resources 136 0 R /Contents 135 0 R >> endobj 13 0 obj << /Type /Page /Parent 123 0 R /Resources 138 0 R /Contents 137 0 R >> endobj 18 0 obj << /Type /Page /Parent 123 0 R /Resources 143 0 R /Contents 142 0 R >> endobj 19 0 obj << /Title (1\tINTRODUCTION) /Dest [ 18 0 R /FitH 757 ] /Parent 305 0 R /Prev 5 0 R /Next 27 0 R /Count 0 >> endobj 21 1 obj << /S /GoTo /D [ 91 0 R /FitH 586 ] >> endobj 22 0 obj << /Type /Page /Parent 123 0 R /Resources 145 0 R /Contents 144 0 R >> endobj 23 1 obj << /S /GoTo /D [ 96 0 R /FitH 740 ] >> endobj 24 0 obj << /Type /Page /Parent 123 0 R /Resources 147 0 R /Contents 146 0 R >> endobj 25 1 obj << /S /GoTo /D [ 96 0 R /FitH 740 ] >> endobj 26 0 obj << /Type /Page /Parent 152 0 R /Resources 154 0 R /Contents 153 0 R >> endobj 27 0 obj << /Title (2\tWHY AND WHAT SHOULD WE REGULATE?) /Dest [ 26 0 R /FitH 757 ] /Parent 305 0 R /Prev 19 0 R /Next 32 0 R /Count 0 >> endobj 29 0 obj << /Type /Page /Parent 152 0 R /Resources 156 0 R /Contents 155 0 R >> endobj 31 0 obj << /Type /Page /Parent 152 0 R /Resources 158 0 R /Contents 157 0 R >> endobj 32 0 obj << /Title (3\tPOLITICAL/SOCIAL DECISION MAKING AND COST BEARING) /Dest [ 31 0 R /FitH 757 ] /Parent 305 0 R /Prev 27 0 R /Next 62 0 R /Count 0 >> endobj 34 0 obj << /Type /Page /Parent 152 0 R /Resources 160 0 R /Contents 159 0 R >> endobj 36 0 obj << /Type /Page /Parent 152 0 R /Resources 165 0 R /Contents 164 0 R >> endobj 39 0 obj << /Type /Page /Parent 152 0 R /Resources 167 0 R /Contents 166 0 R >> endobj 41 0 obj << /Type /Page /Parent 152 0 R /Resources 170 0 R /Contents 169 0 R >> endobj 47 0 obj << /Type /Page /Parent 152 0 R /Resources 172 0 R /Contents 171 0 R >> endobj 50 0 obj << /Type /Page /Parent 176 0 R /Resources 181 0 R /Contents 180 0 R >> endobj 52 0 obj << /Type /Page /Parent 176 0 R /Resources 183 0 R /Contents 182 0 R >> endobj 54 0 obj << /Type /Page /Parent 176 0 R /Resources 185 0 R /Contents 184 0 R >> endobj 57 0 obj << /Type /Page /Parent 176 0 R /Resources 187 0 R /Contents 186 0 R >> endobj 59 0 obj << /Type /Page /Parent 176 0 R /Resources 192 0 R /Contents 191 0 R >> endobj 61 0 obj << /Type /Page /Parent 176 0 R /Resources 197 0 R /Contents 196 0 R >> endobj 62 0 obj << /Title (4\tIMPLEMENTATION) /Dest [ 61 0 R /FitH 757 ] /Parent 305 0 R /Prev 32 0 R /Next 79 0 R /Count 0 >> endobj 63 0 obj << /Type /Page /Parent 200 0 R /Resources 199 0 R /Contents 198 0 R >> endobj 71 0 obj << /Type /Page /Parent 200 0 R /Resources 202 0 R /Contents 201 0 R >> endobj 73 0 obj << /Type /Page /Parent 200 0 R /Resources 204 0 R /Contents 203 0 R >> endobj 76 0 obj << /Type /Page /Parent 200 0 R /Resources 209 0 R /Contents 208 0 R >> endobj 78 0 obj << /Type /Page /Parent 200 0 R /Resources 214 0 R /Contents 213 0 R >> endobj 79 0 obj << /Title (5\tCAN WE SEPARATE DECISION MAKING FROM IMPLEMENTATION?) /Dest [ 78 0 R /FitH 757 ] /Parent 305 0 R /Prev 62 0 R /Next 90 0 R /Count 0 >> endobj 82 0 obj << /Type /Page /Parent 200 0 R /Resources 216 0 R /Contents 215 0 R >> endobj 84 0 obj << /Type /Page /Parent 200 0 R /Resources 218 0 R /Contents 217 0 R >> endobj 87 0 obj << /Type /Page /Parent 200 0 R /Resources 220 0 R /Contents 219 0 R >> endobj 89 0 obj << /Type /Page /Parent 224 0 R /Resources 226 0 R /Contents 225 0 R >> endobj 90 0 obj << /Title (6\tACCOUNTABILITY OF GOVERNMENT) /Dest [ 89 0 R /FitH 757 ] /Parent 305 0 R /Prev 79 0 R /Next 110 1 R /Count 0 >> endobj 91 0 obj << /Type /Page /Parent 224 0 R /Resources 231 0 R /Contents 230 0 R >> endobj 96 0 obj << /Type /Page /Parent 224 0 R /Resources 242 0 R /Contents 241 0 R >> endobj 97 0 obj << /Title (APPENDICES) /Dest [ 96 0 R /FitH 740 ] /First 98 0 R /Last 115 0 R /Count 5 /Next 117 0 R /Prev 110 1 R /Parent 305 0 R >> endobj 98 0 obj << /Title (Appendix One: The Resource Management Act 1991) /Dest [ 96 0 R /FitH 711 ] /Next 106 0 R /Parent 97 0 R >> endobj 100 0 obj << /Type /Page /Parent 224 0 R /Resources 244 0 R /Contents 243 0 R >> endobj 103 0 obj << /Type /Page /Parent 224 0 R /Resources 246 0 R /Contents 245 0 R >> endobj 105 0 obj << /Type /Page /Parent 250 0 R /Resources 252 0 R /Contents 251 0 R >> endobj 106 0 obj << /Title (Appendix Two: Why and what should we regulate?) /Dest [ 105 0 R /FitH 757 ] /Parent 97 0 R /Next 108 0 R /Prev 98 0 R >> endobj 107 0 obj << /Type /Page /Parent 250 0 R /Resources 272 0 R /Contents 271 0 R >> endobj 108 0 obj << /Title (Appendix Three: The Tiebout Model of Mobility and Preference Revelation) /Dest [ 107 0 R /FitH 757 ] /Parent 97 0 R /Prev 106 0 R /Next 113 0 R >> endobj 109 0 obj << /Type /Page /Parent 278 0 R /Resources 277 0 R /Contents 276 0 R >> endobj 110 1 obj << /Title (7 CONCLUSIONS AND RECOMMENDATIONS) /A 21 1 R /Count 0 /Next 97 0 R /Prev 90 0 R /Parent 305 0 R >> endobj 111 1 obj << /S /URI >> endobj 112 0 obj << /Type /Page /Parent 278 0 R /Resources 283 0 R /Contents 282 0 R >> endobj 113 0 obj << /Title (Appendix Four: Other Externalities) /Dest [ 112 0 R /FitH 757 ] /Parent 97 0 R /Prev 108 0 R /Next 115 0 R >> endobj 114 0 obj << /Type /Page /Parent 278 0 R /Resources 291 0 R /Contents 290 0 R >> endobj 115 0 obj << /Title (Appendix Five: Equitable sharing of costs and benefits) /Dest [ 114 0 R /FitH 757 ] /Parent 97 0 R /Prev 113 0 R >> endobj 116 0 obj << /Type /Page /Parent 278 0 R /Resources 296 0 R /Contents 295 0 R >> endobj 117 0 obj << /Title (REFERENCES) /Dest [ 116 0 R /FitH 757 ] /Parent 305 0 R /Prev 97 0 R >> endobj 118 0 obj << /Length 5888 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F3 1 Tf
+12 0 2.551 12 99.36 81.44 Tm
+0 0 1 rg
+0.006 Tc
+0.136 Tw
+[(D)8(i)4(sclaim)15(e)2(r)15(:)-1( T)17(h)-3(e vie)22(w)4(s ex)22(pr)15(esse)22(d ar)15(e t)19(hose )20(of )20(the)22( )-20(au)17(thor)15(\()19(s)2(\) )-20(a)22(nd do no)17(t)]TJ
+0.2551 -1.2 TD
+0.077 Tw
+[(necess)21(ar)14(ily r)14(e)1(flec)21(t t)18(h)-4(e vie)21(w)3(s o)16(f)-2( t)18(h)-4(e N)7(e)1(w )20(Zeala)21(nd )20(Tr)14(easur)14(y)1(. )20( )-20(Th)16(e )-20(Tr)14(eas)21(ur)14(y)]TJ
+0.2508 -1.18 TD
+0.476 Tw
+[(takes )40(no )20(r)15(e)2(s)22(p)-3(o)17(n)-3(sibi)24(lity )40(for)15( )20(an)17(y er)15(r)15(o)-3(r)15(s)2( or)15( om)15(issi)24(ons i)24(n)-3(, )20(or)15( for)15( t)19(h)-3(e)]TJ
+0.2551 -1.2 TD
+-0.003 Tw
+[(cor)14(r)14(ectnes)21(s)1( o)16(f)-2(, t)18(h)-4(e in)16(for)14(m)14(a)1(tio)16(n)-4( c)21(ont)18(aine)21(d in)16( th)16(ese w)23(o)-4(r)14(k)1(ing)16( pa)21(per)14(s)1(.)]TJ
+28.08 0 0 28.08 109.68 730.155 Tm
+-0.002 Tc
+0.006 Tw
+[(TREASURY WORKI)-6(NG PAPER)]TJ
+6.2308 -1.6838 TD
+0.001 Tc
+(98/7)Tj
+25.92 0 0 25.92 112.08 624.001 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+[(Devolutio)-9(n and )-9(the Ne)-9(w Zea)-9(land)]TJ
+1.2778 -1.1944 TD
+[(Resourc)-9(e Man)-9(ageme)-9(nt Act)]TJ
+/F5 1 Tf
+0.0833 -1.7283 TD
+[(Suzi Kerr)-10(, Meg)-9(an Clari)-9(dge &)]TJ
+2.5648 -1.1574 TD
+[(Dominic M)-10(ilicich*)]TJ
+/F3 1 Tf
+12 0 2.551 12 119.52 487.28 Tm
+0.006 Tc
+-0.004 Tw
+[(\(C)8(on)17(tr)15(act t)19(o)-3( N)8(e)2(w )20(Zeala)22(nd )20(Tr)15(easur)15(y)2(, m)15(a)22(nage)22(d b)17(y)2( B)8(e)2(n)17(e)2(dik)22(t)-1(e Je)22(nse)22(n)-3(\))]TJ
+12 0 0 12 99.36 456.008 Tm
+-0.003 Tc
+[(ABST)-12(RACT)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 429.855 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 430.22 Tm
+0.003 Tc
+0.019 Tw
+[(Many )20(past )40(and )20(p)19(o)-1(tenti)5(a)-1(l)5( N)5(e)-1(w)5( )20(Zeal)5(a)19(nd r)16(e)-1(for)16(m)-4(s i)5(n)-1(vol)5(v)3(e si)5(gni)5(fi)5(c)23(ant dev)23(ol)5(uti)5(on, i)5(.)21(e.)]TJ
+0 -1.16 TD
+0.039 Tw
+[(the trans)23(fer o)19(f)1( auth)19(o)-1(ri)5(ty to )20(make )20(deci)5(s)3(i)5(ons on)19( behal)5(f)21( )-20(of )-20(soci)5(ety from)16( )-20(a )-20(hi)5(gh)19(er )-20(to)]TJ
+T*
+0.004 Tc
+0.278 Tw
+[(a l)6(o)0(w)6(e)0(r l)6(e)0(vel)6( )20(of gove)20(r)-3(nme)20(n)0(t. In )20(parti)6(cul)26(a)0(r th)20(e R)6(e)0(sou)20(r)-3(ce Ma)20(nage)20(ment A)11(c)4(t)]TJ
+T*
+0.118 Tw
+[(\(R)6(MA)11(\), the )20(heal)6(th )20(and ed)20(ucati)6(on )20(refo)20(rms, a)20(nd deci)6(s)4(i)6(o)20(ns abou)20(t )-20(the )-20(i)6(n)0(s)24(t)2(i)6(t)2(uti)6(ons)]TJ
+0 -1.14 TD
+0.003 Tc
+0.299 Tw
+[(for )20(add)19(ressi)5(ng )40(Maori)5( i)5(s)3(s)23(ues hav)23(e l)5(ed to si)25(gni)5(fi)5(cant )20(devol)5(uti)5(o)-1(n)19( of aut)21(hori)5(t)1(y.)]TJ
+0 -1.16 TD
+0.004 Tc
+0.398 Tw
+[(E)11(m)-3(pl)6(oyment )20(pol)6(i)6(cy and s)24(o)0(ci)6(al)6( w)6(e)0(l)6(f)2(ar)17(e are)20( areas)24( w)6(here)20( devol)6(uti)26(on i)6(s)4( )-20(an)]TJ
+T*
+0.003 Tc
+0.259 Tw
+[(i)5(m)-4(porta)19(nt )20(pol)5(i)5(cy )20(op)19(ti)5(on. )20(The )20(rol)5(e)-1( an)19(d functi)5(o)19(n)-1( of l)5(o)-1(cal)5( )20(gover)16(nment)21( al)5(so i)5(s)]TJ
+T*
+0.299 Tw
+[(i)5(nherentl)5(y)3( )40(an i)5(ssue )20(of the )20(appr)16(opri)5(a)-1(te)19( l)5(e)-1(vel)5( of d)19(e)-1(vol)5(u)-1(ti)5(on)19(. Ma)19(ny of th)19(ese)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(refor)17(m)-3(s )20(have )40(now)6( )20(bee)20(n )20(i)6(n)0( )20(pl)6(ace)20( )20(for )40(a )20(num)17(ber o)20(f)2( years)24(,)2( so i)6(t)2( i)6(s)4( a)20(pprop)20(ri)6(ate t)22(o)]TJ
+0 -1.14 TD
+0.003 Tc
+0.239 Tw
+[(revi)5(ew)5( our)16( expe)19(ri)5(ence of)21( devol)5(uti)5(o)19(n, i)5(den)19(ti)5(fy the succ)23(esses, an)19(d atte)19(mpt )-20(to)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(address t)21(he pr)16(obl)5(ems )20(that h)19(a)-1(ve ari)5(s)23(en.)]TJ
+10.08 0 0 10.08 99.36 277.215 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 263.66 Tm
+0.003 Tc
+0.039 Tw
+[(Tw)5(o pape)19(rs ad)19(dress i)5(ssu)19(es of w)5(h)-1(e)19(n)-1( and )20(how)5( w)5(e)-1( sho)19(u)-1(l)5(d)-1( devol)5(v)23(e)-1( )-20(auth)19(o)-1(ri)5(ty )-20(f)21(r)-4(om)]TJ
+T*
+0.059 Tw
+[(central)5( )20(to )20(l)25(o)-1(cal)5( )20(gove)19(r)-4(nm)16(ent. )40(Thi)5(s)3( pap)19(er l)5(ooks a)19(t)1( devol)25(uti)5(on bo)19(th fr)16(om a )20(gener)16(al)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(theoreti)6(c)4(al)6( )20(s)24(t)2(andp)20(oi)6(nt )20(an)20(d )20(fro)20(m)-3( the )20(persp)20(ecti)6(ve of t)22(he N)6(e)0(w)6( Z)15(eal)6(and)20( R)6(e)0(sourc)24(e)]TJ
+0 -1.16 TD
+0.002 Tc
+0.32 Tw
+[(M)-5(anage)18(m)-5(ent A)9(c)2(t 1)18(991 \()-5(R)24(M)-5(A)9(\))-5(,)0( with )20(r)-5(e)-2(sidential l)24(and us)22(e as an illust)20(r)-5(a)-2(tion)18(.)]TJ
+T*
+0.004 Tc
+0.458 Tw
+[(A)11(l)6(though )20(the )20(R)26(M)-3(A)11( )20(i)6(s)4( di)6(scussed t)22(h)0(rou)20(ghout )20(both p)20(apers,)22( the f)22(r)-3(amew)26(ork)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(devel)5(oped )40(appl)5(i)5(e)-1(s )20(to)19( )20(any )20(a)19(r)-4(ea )20(of)21( pol)5(i)5(cy fo)19(r w)5(h)-1(i)5(c)3(h dev)23(ol)5(uti)5(on d)19(e)-1(ci)5(si)5(ons a)19(r)-4(e bei)5(n)19(g)]TJ
+T*
+0.004 Tc
+0.198 Tw
+[(consi)6(dered)20(. Th)20(e secon)20(d)0( pap)20(er, )20(Treas)24(ury W)8(o)0(rki)6(n)20(g )-20(P)11(aper 98/7a,)22( )-20(appl)6(i)6(e)0(s )-20(t)22(h)0(e)]TJ
+0 -1.14 TD
+0.003 Tc
+0.319 Tw
+[(framew)5(o)19(r)-4(k )20(to )20(t)21(he opti)25(m)-4(al)5( patt)21(e)-1(rn o)19(f)1( devol)5(u)19(t)1(i)5(on fo)19(r pol)5(i)5(c)3(i)5(e)-1(s r)16(e)-1(l)5(a)-1(ti)5(ng t)21(o)-1( ki)5(w)5(i)]TJ
+0 -1.16 TD
+[(protecti)5(on)19(.)]TJ
+12 0 2.551 12 99.36 124.88 Tm
+0.004 Tc
+0.018 Tw
+[(*)13( S)11(u)0(zi)6( K)11(e)0(rr - U)6(n)0(i)6(v)4(ersi)6(ty )20(of Ma)20(ryl)6(and a)20(t)2( C)6(o)0(l)6(l)6(ege P)11(a)20(rk, Me)20(gan C)6(l)6(a)0(ri)26(dge )-20(&)11( )-20(D)6(o)0(mi)6(ni)6(c)]TJ
+0.2466 -1.16 TD
+-0.001 Tc
+0.003 Tw
+[(M)-8(ilicich)-5( \226)-5( NZ)-10( )20(T)-10(r)-8(e)-5(a)-5(s)-1(u)15(r)-8(y.)]TJ
+ET
+endstream endobj 119 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 120 0 obj << /Type /Font /Subtype /Type1 /Name /F3 /Encoding 304 0 R /BaseFont /Helvetica-Bold >> endobj 121 0 obj << /Type /Font /Subtype /Type1 /Name /F5 /Encoding 304 0 R /BaseFont /Helvetica >> endobj 122 0 obj << /Type /ExtGState /SA false /OP false /HT /Default >> endobj 123 0 obj << /Type /Pages /Kids [ 1 0 R 124 0 R 130 0 R 4 0 R 7 0 R 13 0 R 139 0 R 18 0 R 22 0 R 24 0 R ] /Count 10 /Parent 151 0 R >> endobj 124 0 obj << /Type /Page /Parent 123 0 R /Resources 126 0 R /Contents 125 0 R >> endobj 125 0 obj << /Length 15459 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F3 1 Tf
+13.92 0 0 13.92 281.76 726.793 Tm
+0 0 0 rg
+0.002 Tc
+[(Co)10(n)-8(t)7(e)-11(n)10(t)-10(s)]TJ
+/F7 1 Tf
+10.08 0 0 10.08 99.36 708.556 Tm
+-0.008 Tc
+[(AB)-32(ST)-8(RACT)]TJ
+5.5952 0 TD
+0.012 Tc
+(...............................................................................................................................)Tj
+33.2633 0 TD
+[(..........)-214(1)]TJ
+-38.8585 -2.3333 TD
+0 Tw
+[(E)12(X)20(E)12(C)20(U)20(T)12(I)20(V)20(E)12( S)20(U)20(M)27(MA)20(R)43(Y)-169(..............................................................................................................)]TJ
+40.4292 0 TD
+[(....)-213(3)]TJ
+-40.4292 -2.3333 TD
+0 Tc
+0.012 Tw
+[(S)8(e)-8(p)8(a)0(r)-8(a)0(b)8(i)16(l)-8(i)-8(t)0(y)24( o)24(f)0( I)8(m)23(p)8(l)-8(e)-8(m)23(e)-8(n)8(tati)-8(o)24(n)8( fr)-8(o)24(m)23( D)8(e)-8(c)15(i)-8(s)8(i)-8(o)24(n)8(-M)-9(a)24(k)-16(i)-8(n)8(g?)]TJ
+23.6667 0 TD
+0.012 Tc
+[(....................................................................)-214(5)]TJ
+-23.6667 -2.3333 TD
+-0.008 Tc
+[(1)-1889(INT)-8(RO)-16(DUCT)-8(IO)-16(N)]TJ
+10.5714 0 TD
+0.012 Tc
+[(......................................................................................................................)-213(7)]TJ
+/F9 1 Tf
+-8.1905 -1.7141 TD
+-0.024 Tw
+[(D)20(evo)36(lu)12(t)28(i)4(o)12(n)12( a)12(n)12(d)36( )-24(d)12(e)27(cen)36(tr)20(a)12(l)28(is)20(a)12(t)4(i)28(o)12(n)-33(................................................................................................)]TJ
+38.0476 0 TD
+[(....)-214(7)]TJ
+-38.0476 -1.1429 TD
+0 Tc
+0.012 Tw
+[(T)8(h)0(e)-8( )24(R)-8(e)-8(s)8(our)32(c)-8(e)15( Mana)24(ge)-8(m)31(e)-8(nt)16( A)16(c)-8(t)]TJ
+12.6429 0 TD
+0.012 Tc
+[(.....................................................................................................)-214(8)]TJ
+-12.6429 -1.1429 TD
+0 Tw
+[(Aim)20(s)20( a)36(n)12(d)12( s)44(t)4(r)20(u)12(ct)28(u)12(r)20(e)27( o)12(f)28( th)36(is)20( p)12(a)36(p)12(e)4(r)-49(...............................................................................................)]TJ
+37.7871 0 TD
+[(.....)-214(9)]TJ
+/F7 1 Tf
+-40.168 -1.7621 TD
+[(2)-1869(W)12(H)28(Y)-4( A)20(N)20(D)43( W)36(H)4(A)20(T)12( S)44(HOU)43(L)14(D)20( W)36(E)12( R)20(E)36(GU)20(L)12(A)20(T)12(E)36(?)-82(...................................................................)-238(1)12(1)]TJ
+/F11 1 Tf
+1.1905 -1.6903 TD
+0 Tc
+(E)Tj
+7.92 0 0 7.92 117.6 562.672 Tm
+-0.003 Tc
+0.026 Tw
+[(X)22(T)-28(ERN)-39(A)22(LIT)-28(I)-3(ES)-23( A)22(N)-8(D)-8( )]TJ
+10.08 0 0 10.08 195.36 562.878 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 201.12 562.672 Tm
+0.003 Tc
+[(UBL)8(I)3(C)-27( )]TJ
+10.08 0 0 10.08 227.04 562.878 Tm
+0 Tc
+(G)Tj
+7.92 0 0 7.92 234.24 562.672 Tm
+0.005 Tc
+[(OOD)-31(S)]TJ
+10.08 0 0 10.08 256.08 562.878 Tm
+0.012 Tc
+[(.................................................................................................)-238(1)12(1)]TJ
+-14.3571 -1.1429 TD
+0 Tc
+(I)Tj
+7.92 0 0 7.92 114.72 551.152 Tm
+0.003 Tc
+0.02 Tw
+[(NF)13(ORM)-17(A)28(T)-22(I)3(ON F)-17(A)28(IL)-22(URE)-22(S)]TJ
+10.08 0 0 10.08 208.56 551.358 Tm
+0.012 Tc
+[(...................................................................................................................)-237(1)12(2)]TJ
+/F7 1 Tf
+-10.8333 -1.7621 TD
+-0.008 Tc
+[(3)-1889(P)8(O)-16(L)-8(IT)-8(ICAL)-8(/)-16(S)0(O)-16(CIAL)-8( D)25(E)-8(CISIO)-16(N )24(M)-17(A)0(K)-16(ING)8( AND C)23(O)-16(ST)16( )24(B)-32(E)-8(ARING)]TJ
+32.0476 0 TD
+0.012 Tc
+[(..................................)-238(1)12(3)]TJ
+/F11 1 Tf
+-30.8571 -1.7141 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 516.112 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 516.318 Tm
+0 Tc
+(P)Tj
+7.92 0 0 7.92 135.6 516.112 Tm
+-0.001 Tc
+-0.007 Tw
+[(ROBL)-26(EM)-21( WIT)-26(H)-6( )]TJ
+10.08 0 0 10.08 193.68 516.318 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 199.44 516.112 Tm
+-0.001 Tc
+[(U)24(B)-31(LIC )]TJ
+10.08 0 0 10.08 225.12 516.318 Tm
+0 Tc
+(G)Tj
+7.92 0 0 7.92 232.56 516.112 Tm
+0.005 Tc
+(OODS)Tj
+10.08 0 0 10.08 254.16 516.318 Tm
+0.008 Tc
+0.004 Tw
+(: P)Tj
+7.92 0 0 7.92 265.2 516.112 Tm
+-0.001 Tc
+[(REF)-21(E)4(RE)-26(NCE )]TJ
+10.08 0 0 10.08 312.96 516.318 Tm
+0 Tc
+0 Tw
+(R)Tj
+7.92 0 0 7.92 319.68 516.112 Tm
+-0.001 Tc
+[(E)-26(V)24(EL)-26(A)24(T)-26(ION)]TJ
+10.08 0 0 10.08 366.96 516.318 Tm
+0.012 Tc
+[(.......................................................)-237(1)12(3)]TJ
+-25.3571 -1.1429 TD
+0 Tc
+(S)Tj
+7.92 0 0 7.92 116.88 504.592 Tm
+0.003 Tc
+[(OCI)-28(A)28(L)8( )]TJ
+10.08 0 0 10.08 143.04 504.798 Tm
+0 Tc
+(C)Tj
+7.92 0 0 7.92 149.76 504.592 Tm
+0.003 Tc
+[(HOI)-28(CE)8( )]TJ
+10.08 0 0 10.08 176.16 504.798 Tm
+0 Tc
+(M)Tj
+7.92 0 0 7.92 185.28 504.592 Tm
+-0.006 Tc
+[(ECH)-42(A)19(N)-11(I)-37(SM)-26(S)]TJ
+10.08 0 0 10.08 232.32 504.798 Tm
+0.012 Tc
+[(..........................................................................................................)-238(1)12(4)]TJ
+-12 -1.1429 TD
+0 Tc
+(W)Tj
+7.92 0 0 7.92 120.72 493.072 Tm
+0.005 Tc
+-0.013 Tw
+[(HE)10(N DO)-31(E)10(S)-15( )]TJ
+10.08 0 0 10.08 162 493.278 Tm
+0 Tc
+0 Tw
+(D)Tj
+7.92 0 0 7.92 169.2 493.072 Tm
+0.004 Tc
+[(E)-21(V)29(OL)-21(U)29(T)-21(ION )]TJ
+10.08 0 0 10.08 217.2 493.278 Tm
+0 Tc
+(I)Tj
+7.92 0 0 7.92 220.8 493.072 Tm
+[(M)10(P)-20(RO)-36(V)25(E)-25( )]TJ
+10.08 0 0 10.08 256.08 493.278 Tm
+(S)Tj
+7.92 0 0 7.92 261.6 493.072 Tm
+0.003 Tc
+[(OCI)-28(A)-2(L)8( )]TJ
+10.08 0 0 10.08 288 493.278 Tm
+0 Tc
+(C)Tj
+7.92 0 0 7.92 294.72 493.072 Tm
+0.002 Tc
+(HOICE)Tj
+10.08 0 0 10.08 319.2 493.278 Tm
+0.012 Tc
+[(?)-92(.......................................................................)-238(1)12(6)]TJ
+/F9 1 Tf
+-19.4286 -1.1429 TD
+[(I)12(n)12(f)4(o)12(r)20(m)20(e)4(d)36( d)36(ecis)44(io)12(n)36( m)20(a)12(k)27(i)4(n)12(g)-153(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(1)12(6)]TJ
+-37.5241 -1.1429 TD
+[(Ba)12(la)12(n)36(c)27(ed)12( d)36(e)4(c)27(i)4(s)20(i)4(o)12(n)36( m)20(a)36(kin)12(g)-34(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(1)12(7)]TJ
+-37.5241 -1.1429 TD
+[(C)12(o)12(s)20(t )24(ef)28(fe)27(cti)28(ve)27( d)36(e)4(c)27(i)4(s)20(i)4(o)12(n)36( m)20(a)12(k)27(i)4(n)12(g)14(.................................................................................................)]TJ
+37.5238 0 TD
+[(....)-238(2)12(2)]TJ
+/F7 1 Tf
+-39.9048 -1.7621 TD
+0 Tc
+0.012 Tw
+[(EX)8(A)8(M)-9(P)16(LE: )24( T)24(H)-8(E)24( P)16(L)0(A)8(C)8(E)0(M)-9(E)0(N)8(T)24( )24(O)-8(F)16( C)8(ELL)24( P)16(H)16(O)-8(N)8(E)0( )24(TO)-8(W)24(E)0(R)8(S)]TJ
+27.5952 0 TD
+0.012 Tc
+[(...................................................)-237(2)12(3)]TJ
+-27.5952 -2.3333 TD
+-0.004 Tc
+0.016 Tw
+[(EXAM)-13(P)12(LE: )24(TH)-12(E)20( P)12(L)-4(ACE)20(M)-13(E)-4(NT )24(O)-12(F)12( CE)20(LL P)12(H)12(O)-12(NE)20( T)20(O)-12(WERS C)27(O)-12(NTINUED)]TJ
+33.619 0 TD
+0.012 Tc
+[(............................)-237(2)12(4)]TJ
+-33.619 -2.3095 TD
+0 Tw
+[(F)28(i)4(g)12(u)44(re x)36(x)12(x)13(.....................................................................................................................)]TJ
+35.1914 0 TD
+[(......................)-238(2)12(4)]TJ
+/F11 1 Tf
+-34.0009 -1.7141 TD
+0 Tc
+(T)Tj
+7.92 0 0 7.92 117.6 376.672 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 376.878 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 376.672 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 376.878 Tm
+0.008 Tc
+0.004 Tw
+(: P)Tj
+7.92 0 0 7.92 193.92 376.672 Tm
+0 Tc
+[(OLIT)-25(IC)-30(A)25(L)-25( )]TJ
+10.08 0 0 10.08 232.8 376.878 Tm
+0 Tw
+(D)Tj
+7.92 0 0 7.92 240 376.672 Tm
+0.004 Tc
+[(E)9(C)4(I)-27(S)14(ION )]TJ
+10.08 0 0 10.08 273.6 376.878 Tm
+0 Tc
+(M)Tj
+7.92 0 0 7.92 282.72 376.672 Tm
+0.004 Tc
+0.019 Tw
+[(AK)29(ING A)29(N)-1(D)-32( )]TJ
+10.08 0 0 10.08 329.52 376.878 Tm
+0 Tc
+0 Tw
+(C)Tj
+7.92 0 0 7.92 336.24 376.672 Tm
+0.005 Tc
+[(OS)15(T)-20( )]TJ
+10.08 0 0 10.08 353.28 376.878 Tm
+0 Tc
+(B)Tj
+7.92 0 0 7.92 359.76 376.672 Tm
+[(E)-25(A)-5(RIN)-36(G)]TJ
+10.08 0 0 10.08 390.72 376.878 Tm
+0.012 Tc
+[(..............................................)-237(2)12(5)]TJ
+-27.7143 -1.1429 TD
+0 Tc
+(M)Tj
+7.92 0 0 7.92 120.24 365.152 Tm
+0.003 Tc
+0.02 Tw
+[(OBIL)8(IT)-22(Y A)28(ND )]TJ
+10.08 0 0 10.08 173.28 365.358 Tm
+0 Tc
+0 Tw
+(D)Tj
+7.92 0 0 7.92 180.72 365.152 Tm
+0.004 Tc
+[(E)-21(V)29(OL)-21(U)29(T)-21(ION)]TJ
+10.08 0 0 10.08 227.04 365.358 Tm
+0.012 Tc
+[(............................................................................................................)-238(2)12(7)]TJ
+/F7 1 Tf
+-12.6667 -1.7621 TD
+[(4)-1869(I)20(MP)28(L)12(E)12(M)3(E)12(N)20(T)12(A)43(T)12(I)20(ON)21(...............................................................................................................)-237(2)]TJ
+41.6906 0 TD
+0 Tc
+(9)Tj
+/F9 1 Tf
+-39.3096 -1.7141 TD
+0.012 Tc
+[(D)20(i)4(s)20(eco)12(n)36(o)12(m)20(i)28(es)20( o)12(f)28( s)20(c)27(a)12(l)4(e)27(:)12( )24(fl)28(exi)28(b)12(i)4(l)28(i)4(t)28(y)-208(.............................................................................................)]TJ
+37.787 0 TD
+[(...)-237(3)12(0)]TJ
+-37.787 -1.1429 TD
+0.001 Tw
+[(Eco)11(n)35(o)11(m)19(ies)43( o)11(f)27( s)19(c)3(a)35(l)3(e)26(:)11( )24(eff)27(ic)26(ien)35(c)26(y)-67(.................................................................................................)]TJ
+37.5238 0 TD
+[(....)-238(3)12(1)]TJ
+-37.5238 -1.1429 TD
+[(I)12(n)12(f)4(o)12(r)20(m)20(a)12(t)28(i)4(o)12(n)-11(....................................................................................................................)]TJ
+35.1676 0 TD
+[(.............)-238(3)12(2)]TJ
+-35.1676 -1.1429 TD
+0 Tc
+[(Innov)-8(a)24(t)-8(i)-8(o)24(n)]TJ
+4.5238 0 TD
+0.012 Tc
+(...............................................................................................................................)Tj
+33.2633 0 TD
+[(...)-238(3)12(2)]TJ
+/F11 1 Tf
+-38.9776 -1.1429 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 284.032 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 284.238 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 284.032 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 284.238 Tm
+0.008 Tc
+0.004 Tw
+(: E)Tj
+7.92 0 0 7.92 194.64 284.032 Tm
+0 Tc
+[(F)10(F)10(ICI)-31(ENT)-25( )]TJ
+10.08 0 0 10.08 231.6 284.238 Tm
+0 Tw
+(I)Tj
+7.92 0 0 7.92 234.96 284.032 Tm
+0.001 Tc
+[(M)-19(P)11(LE)-24(M)11(E)6(NT)-55(A)26(T)-24(ION)]TJ
+10.08 0 0 10.08 306.24 284.238 Tm
+0.012 Tc
+[(..............................................................................)-237(3)12(4)]TJ
+/F7 1 Tf
+-20.5238 -1.7621 TD
+-0.008 Tc
+0.02 Tw
+[(5)-1889(CAN W)-8(E)-8( S)24(E)-8(P)8(ARAT)-8(E)-8( DE)-6(CISIO)-16(N )24(M)-17(A)23(K)-16(ING)-16( F)8(R)0(O)8(M)7( IM)-17(P)8(L)-8(E)16(M)-17(E)-8(N)0(T)-8(A)0(T)-8(I)24(O)-16(N)0(?)]TJ
+35.1905 0 TD
+0.012 Tc
+[(......................)-237(3)12(6)]TJ
+/F9 1 Tf
+-32.8095 -1.7141 TD
+0 Tc
+0.012 Tw
+[(Cont)-8(r)8(a)0(c)15(t)-8(i)-8(n)24(g pr)8(o)24(b)0(l)-8(e)-8(m)8(s)]TJ
+8.9762 0 TD
+0.012 Tc
+[(.................................................................................................................)-237(3)12(6)]TJ
+-8.9762 -1.119 TD
+0 Tw
+[(S)12(o)12(l)4(u)12(t)28(io)12(n)12(s)20( )24(to)36( co)36(n)12(t)4(r)20(a)12(c)27(tin)36(g)12( p)12(r)20(o)12(b)36(lem)20(s)-168(..............................................................................................)]TJ
+38.3109 0 TD
+0.249 Tc
+[(.3)249(7)]TJ
+-38.3109 -1.1429 TD
+0.009 Tc
+0.003 Tw
+[(Ad)9(va)33(n)9(t)1(a)9(g)33(es)17( o)33(f)1( s)41(e)1(p)9(a)9(r)17(a)9(t)25(in)9(g)33( p)9(o)33(lit)25(ica)33(l )24(a)9(n)9(d)33( im)17(p)33(lem)17(e)24(n)9(ta)33(tio)9(n)33( r)17(o)9(l)25(e)1(s)17(:)9( )24(th)9(e)24( r)17(e)24(g)9(u)9(l)1(a)33(t)1(o)9(r)17( )24(/ p)9(r)17(o)33(v)1(i)25(d)9(er)17( s)17(p)33(li)25(t)-183(.........)-241(3)9(8)]TJ
+/F11 1 Tf
+-1.1905 -1.1429 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 214.672 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 214.878 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 214.672 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 214.878 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 194.64 214.672 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 207.12 214.878 Tm
+0 Tc
+0 Tw
+(W)Tj
+7.92 0 0 7.92 216.48 214.672 Tm
+-0.005 Tc
+[(H)-10(O)-41(LE )]TJ
+10.08 0 0 10.08 239.76 214.878 Tm
+0 Tc
+(P)Tj
+7.92 0 0 7.92 245.28 214.672 Tm
+0.031 Tc
+[(IC)31(T)6(U)56(RE)]TJ
+10.08 0 0 10.08 274.56 214.878 Tm
+0.012 Tc
+[(..........................................................................................)-237(3)12(9)]TJ
+/F7 1 Tf
+-17.3809 -1.7621 TD
+-0.008 Tc
+-0.004 Tw
+[(6)-1889(ACCO)-16(UNT)-8(A)23(B)-32(IL)-8(IT)-8(Y O)-16(F)8( )-22(G)8(O)-16(VE)-8(RN)23(M)-17(E)-8(NT)]TJ
+21.0476 0 TD
+0.012 Tc
+[(............................................................................)-238(4)12(1)]TJ
+/F9 1 Tf
+-18.6667 -1.7141 TD
+0 Tw
+[(S)12(o)12(ver)44(eig)12(n)36(t)4(y)27( is)20(s)20(u)36(es)-74(.............................................................................................................)]TJ
+35.953 0 TD
+[(..........)-237(4)12(3)]TJ
+/F7 1 Tf
+-38.3339 -1.7621 TD
+-0.008 Tc
+[(AP)8(P)8(E)-8(NDICE)-8(S)]TJ
+6.3809 0 TD
+0.012 Tc
+(...............................................................................................................................)Tj
+33.2633 0 TD
+[(.....)-238(4)12(7)]TJ
+/F11 1 Tf
+-38.4538 -1.7141 TD
+0 Tc
+(A)Tj
+7.92 0 0 7.92 118.56 144.592 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 144.798 Tm
+0 Tc
+(O)Tj
+7.92 0 0 7.92 161.28 144.592 Tm
+0.036 Tc
+(NE)Tj
+10.08 0 0 10.08 172.08 144.798 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 183.84 144.592 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 196.32 144.798 Tm
+0 Tc
+0 Tw
+(R)Tj
+7.92 0 0 7.92 202.8 144.592 Tm
+[(E)-25(S)10(O)-36(U)25(RCE)-25( )]TJ
+10.08 0 0 10.08 241.2 144.798 Tm
+(M)Tj
+7.92 0 0 7.92 250.32 144.592 Tm
+-0.025 Tc
+[(AN)-61(AG)-61(E)-20(M)-15(E)-50(N)-30(T)-50( )]TJ
+10.08 0 0 10.08 302.88 144.798 Tm
+0 Tc
+(A)Tj
+7.92 0 0 7.92 310.08 144.592 Tm
+[(CT)-25( )]TJ
+10.08 0 0 10.08 322.32 144.798 Tm
+(1991)Tj
+2.0714 0 TD
+0.012 Tc
+[(................................................................)-237(4)12(7)]TJ
+/F9 1 Tf
+-21.8095 -1.1429 TD
+[(M)12(a)12(j)4(o)12(r)20( )24(As)20(p)12(e)27(cts)44( o)12(f)28( t)28(h)12(e)27( RM)35(A)6(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(4)12(7)]TJ
+-37.5241 -1.1429 TD
+[(Ro)12(l)28(e)4( o)36(f)4( )24(C)12(e)4(n)36(t)4(r)20(a)12(l)28( G)20(o)12(v)27(e)4(r)20(n)12(m)20(e)4(n)36(t)-41(.....................................................................................................)]TJ
+37.7859 0 TD
+[(...)-238(4)12(8)]TJ
+-37.7859 -1.1429 TD
+[(Ro)12(l)28(e)4(s)20( o)36(f)4( L)20(o)36(ca)12(l)28( A)28(u)12(th)12(o)12(r)44(iti)28(es)-121(.....................................................................................................)]TJ
+37.0002 0 TD
+[(......)-238(4)12(8)]TJ
+-37.0002 -1.1429 TD
+[(P)28(u)12(b)12(lic)27( P)28(a)12(r)20(t)4(i)28(cip)12(a)36(tio)36(n)-34(...........................................................................................................)]TJ
+36.2148 0 TD
+[(.........)-237(4)12(9)]TJ
+ET
+endstream endobj 126 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F7 127 0 R /F9 128 0 R /F11 129 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 127 0 obj << /Type /Font /Subtype /Type1 /Name /F7 /Encoding 304 0 R /BaseFont /Times-Bold >> endobj 128 0 obj << /Type /Font /Subtype /Type1 /Name /F9 /Encoding 304 0 R /BaseFont /Times-Italic >> endobj 129 0 obj << /Type /Font /Subtype /Type1 /Name /F11 /Encoding 304 0 R /BaseFont /Times-Roman >> endobj 130 0 obj << /Type /Page /Parent 123 0 R /Resources 132 0 R /Contents 131 0 R >> endobj 131 0 obj << /Length 8549 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(2)Tj
+/F9 1 Tf
+10.08 0 0 10.08 123.36 748.158 Tm
+0.012 Tc
+[(L)20(o)12(ca)12(l)28( G)20(o)12(v)27(e)4(r)20(n)12(m)20(e)4(n)36(t)4( )24(Re)27(fo)12(r)20(m)-193(........................................................................................................)]TJ
+38.048 0 TD
+[(..)-238(4)12(9)]TJ
+/F11 1 Tf
+-39.2384 -1.1429 TD
+0 Tc
+(A)Tj
+7.92 0 0 7.92 118.56 736.432 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 736.638 Tm
+0 Tc
+(T)Tj
+7.92 0 0 7.92 160.32 736.432 Tm
+-0.004 Tc
+(WO)Tj
+10.08 0 0 10.08 173.52 736.638 Tm
+0.008 Tc
+0.004 Tw
+(: W)Tj
+7.92 0 0 7.92 188.4 736.432 Tm
+0.004 Tc
+0.019 Tw
+[(HY A)29(ND W)8(H)-32(A)29(T)-21( )31(S)14(H)-1(O)-32(U)-1(L)9(D)-1( W)8(E)9( RE)9(G)-32(U)29(L)-21(A)29(T)-21(E)]TJ
+10.08 0 0 10.08 338.4 736.638 Tm
+0.012 Tc
+[(?)-20(................................................................)-237(5)12(1)]TJ
+/F9 1 Tf
+-21.3333 -1.1429 TD
+0.001 Tw
+[(Ext)27(er)19(n)11(a)35(lit)27(ies)43( /)27( I)11(n)35(co)11(m)19(p)11(l)27(e)3(t)27(e)3( )24(Al)27(lo)11(ca)35(ti)27(o)11(n)11( o)35(f)3( P)27(r)19(o)11(p)35(er)19(ty)26( R)27(i)3(g)11(h)35(ts)-96(..............................................................)-238(5)11(1)]TJ
+T*
+0 Tw
+[(I)12(n)12(f)4(o)12(r)20(m)20(a)12(t)28(i)4(o)12(n)36( F)28(a)12(ilu)12(r)44(e)4(s)-74(...........................................................................................................)]TJ
+36.4767 0 TD
+[(........)-237(5)12(6)]TJ
+-36.4767 -1.1429 TD
+0.001 Tw
+[(W)34(h)11(a)11(t)3( is)19( )24(th)35(e r)19(o)35(le)26( o)11(f)27( th)35(e )24(RM)34(A?)13(...................................................................................................)]TJ
+37.5239 0 TD
+[(....)-238(5)12(7)]TJ
+/F11 1 Tf
+-38.7144 -1.1429 TD
+0 Tc
+0 Tw
+(A)Tj
+7.92 0 0 7.92 118.56 690.352 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 690.558 Tm
+0 Tc
+(T)Tj
+7.92 0 0 7.92 160.32 690.352 Tm
+0.003 Tc
+[(HRE)-22(E)]TJ
+10.08 0 0 10.08 181.2 690.558 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 192.96 690.352 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 205.44 690.558 Tm
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 211.68 690.352 Tm
+[(IEBOU)25(T)-25( )]TJ
+10.08 0 0 10.08 242.64 690.558 Tm
+(M)Tj
+7.92 0 0 7.92 251.52 690.352 Tm
+0.005 Tc
+-0.013 Tw
+[(ODE)-20(L)10( O)-31(F)15( )]TJ
+10.08 0 0 10.08 287.04 690.558 Tm
+0 Tc
+0 Tw
+(M)Tj
+7.92 0 0 7.92 295.92 690.352 Tm
+0.003 Tc
+0.02 Tw
+[(OBI)-28(L)8(IT)-22(Y A)28(ND )]TJ
+10.08 0 0 10.08 349.2 690.558 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 354.72 690.352 Tm
+0.03 Tc
+[(RE)35(F)10(E)35(R)30(E)35(N)-6(C)30(E)35( )]TJ
+10.08 0 0 10.08 402.48 690.558 Tm
+0 Tc
+(R)Tj
+7.92 0 0 7.92 408.96 690.352 Tm
+-0.001 Tc
+[(E)-57(V)-6(EL)-26(A)24(T)-26(ION)]TJ
+10.08 0 0 10.08 456.72 690.558 Tm
+0.012 Tc
+[(.....................)-237(5)12(8)]TJ
+/F9 1 Tf
+-33.0714 -1.1429 TD
+0 Tc
+0.012 Tw
+[(Mobi)-8(l)16(i)-8(t)16(y)-8( )24(i)-8(n)24( Ne)-8(w)48( Z)8(e)-8(al)-8(an)24(d)]TJ
+10.0238 0 TD
+0.012 Tc
+[(.............................................................................................................)-237(5)12(9)]TJ
+-10.0238 -1.1429 TD
+0.001 Tw
+[(P)27(r)19(o)11(b)11(lem)19(s)19( w)59(ith)11( M)11(o)11(b)35(il)27(it)27(y a)11(n)35(d)11( )24(Ef)27(fi)27(ci)27(en)11(c)26(y)-185(........................................................................................)-238(6)11(0)]TJ
+/F11 1 Tf
+-1.1905 -1.1429 TD
+0 Tc
+0 Tw
+(A)Tj
+7.92 0 0 7.92 118.56 655.792 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 655.998 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 159.6 655.792 Tm
+0.036 Tc
+[(OU)31(R)]TJ
+10.08 0 0 10.08 176.64 655.998 Tm
+0.008 Tc
+0.004 Tw
+(: O)Tj
+7.92 0 0 7.92 189.36 655.792 Tm
+0.025 Tc
+[(TH)20(E)30(R)25( )]TJ
+10.08 0 0 10.08 212.16 655.998 Tm
+0 Tc
+0 Tw
+(E)Tj
+7.92 0 0 7.92 218.4 655.792 Tm
+-0.003 Tc
+[(X)22(T)-28(ERN)-39(A)22(LIT)-28(I)-3(E)-28(S)]TJ
+10.08 0 0 10.08 277.2 655.998 Tm
+0.012 Tc
+[(.........................................................................................)-237(6)12(2)]TJ
+/F9 1 Tf
+-15.2619 -1.1429 TD
+-0.024 Tw
+[(T)20(a)12(x ex)27(ter)20(n)12(a)36(lit)28(ies)-193(..............................................................................................................)]TJ
+35.6911 0 TD
+[(...........)-237(6)12(2)]TJ
+-35.6911 -1.119 TD
+[(ln)11(t)27(e)3(r)19(j)3(u)11(r)19(is)19(d)35(ict)27(io)11(n)11(a)35(l C)11(o)11(m)19(p)11(e)26(ti)27(tio)11(n)-225(................................................................................................)]TJ
+37.7857 0 TD
+[(...)-238(6)12(3)]TJ
+-37.7857 -1.1429 TD
+[(\223)20(N)12(o)12(t)4( in)12( )-24(m)43(y)4( b)12(a)12(c)27(kya)12(r)20(d)12(\224)44( )-24( N)12(I)12(M)35(BY)22(....................................................................................................)]TJ
+38.8095 0 TD
+0 Tc
+(64)Tj
+/F11 1 Tf
+-40 -1.1429 TD
+0 Tw
+(A)Tj
+7.92 0 0 7.92 118.56 609.952 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 610.158 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 159.6 609.952 Tm
+0.031 Tc
+[(IV)26(E)]TJ
+10.08 0 0 10.08 173.04 610.158 Tm
+0.008 Tc
+0.004 Tw
+(: E)Tj
+7.92 0 0 7.92 184.8 609.952 Tm
+0.003 Tc
+-0.011 Tw
+[(QU)28(IT)-22(A)28(B)-27(L)8(E)8( )-31(S)13(H)-33(A)28(RING)-33( OF)-17( COS)13(T)-22(S)-17( )-31(A)28(ND B)-27(E)8(NE)-22(F)13(I)3(T)-22(S)]TJ
+10.08 0 0 10.08 361.68 610.158 Tm
+0.012 Tc
+[(.........................................................)-237(6)12(5)]TJ
+/F7 1 Tf
+-26.0238 -1.7621 TD
+[(R)20(E)12(F)28(E)12(R)20(E)12(N)20(C)20(E)12(S)-217(.....................................................................................................................)]TJ
+37.5485 0 TD
+[(.............)-238(6)12(7)]TJ
+/F3 1 Tf
+12 0 0 12 99.36 545.12 Tm
+0.008 Tc
+-0.026 Tw
+[(Tabl)6(e)24( )-20(of Fi)6(g)19(u)-1(r)17(e)4(s)]TJ
+/F9 1 Tf
+10.08 0 0 10.08 99.36 519.198 Tm
+0.012 Tc
+0 Tw
+[(F)28(i)4(g)12(u)12(r)20(e 1)36( )24( D)20(e)4(v)27(o)12(lu)36(tio)12(n)36( F)28(r)20(a)12(m)20(ew)60(o)12(r)20(k)-232(.................................................................................................)]TJ
+38.8572 0 TD
+[(..........)-214(6)]TJ
+-38.8572 -1.1429 TD
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 2)35( )24( S)11(i)3(n)11(g)35(le)26( a)11(n)35(d)11( D)19(o)11(u)35(b)11(le)26( P)27(e)3(a)35(ked)35( P)27(r)19(ef)27(er)19(en)35(ce)26( D)19(e)3(n)11(s)43(it)27(y F)27(u)11(n)11(c)26(ti)27(o)11(n)11(s)-191(......................................................)-238(1)11(5)]TJ
+T*
+[(F)27(i)3(g)11(u)11(r)19(e 3)11(:)34( D)42(evo)35(lu)11(t)27(i)3(o)11(n)35( a)11(n)11(d)35( P)27(o)11(li)27(ti)27(ca)11(l)27( D)19(e)26(cis)19(i)27(o)11(n)11( )24(M)11(a)11(k)26(in)11(g)-128(............................................................................)-239(2)]TJ
+41.6906 0 TD
+0 Tc
+0 Tw
+(5)Tj
+-41.6906 -1.1429 TD
+0.011 Tc
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 4)11(:)34( D)42(evo)35(lu)11(t)27(i)3(o)11(n)35( a)11(n)11(d)35( E)27(ffi)27(ci)27(en)35(t P)27(r)19(o)11(v)26(is)19(io)11(n)14(...................................................................................)]TJ
+39.6437 0 TD
+[(.....)-237(3)12(4)]TJ
+-39.6437 -1.1429 TD
+0 Tc
+0.012 Tw
+[(F)16(i)-8(gur)8(e)-8( 5)24( )24( D)8(e)-8(v)15(o)0(l)-8(u)24(t)-8(i)-8(o)0(n)24( an)24(d P)16(ubl)16(i)-8(c)15( G)8(oods)]TJ
+15.8095 0 TD
+0.012 Tc
+[(................................................................................................)-237(3)12(9)]TJ
+-15.8095 -1.1429 TD
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 6)35( O)19(v)26(er)19(-)11(p)11(r)19(o)11(d)11(u)35(ct)27(io)11(n)35( o)11(f)27( e)26(x)3(t)27(e)3(r)19(n)11(a)11(l)27(it)27(ies)-26(......................................................................................)]TJ
+39.12 0 TD
+[(.......)-237(5)12(2)]TJ
+-39.12 -1.119 TD
+0 Tc
+0.012 Tw
+[(F)16(i)-8(gur)8(e)-8( 7)24( )24( U)8(nde)-8(r)8(-pr)8(o)24(v)-8(i)-8(s)8(i)16(on )24(of)16( P)16(ubl)-8(i)16(c)-8( G)31(oods)]TJ
+17.3809 0 TD
+0.012 Tc
+[(..........................................................................................)-237(5)12(3)]TJ
+-17.3809 -1.1429 TD
+0 Tc
+[(F)16(i)-8(gur)8(e)-8( 8)24( )24( E)16(c)-8(onom)8(i)16(e)-8(s)8( )24(and D)31(i)-8(s)8(e)15(c)-8(onom)8(i)16(e)-8(s)8( o)24(f)-8( )24(Sc)-8(a)24(l)-8(e)15( i)-8(n)24( Com)8(m)8(u)24(ni)-8(t)16(y)15( Si)-8(z)8(e)]TJ
+27.0714 0 TD
+0.012 Tc
+[(.....................................................)-237(6)12(2)]TJ
+ET
+endstream endobj 132 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F7 127 0 R /F9 128 0 R /F11 129 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 133 0 obj << /Length 6414 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(3)Tj
+/F3 1 Tf
+-34.86 58.94 TD
+-0.005 Tc
+0.027 Tw
+[(EXECUT)-14(I)-7(VE SUM)-12(M)-12(ARY)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.198 Tw
+[(Thi)6(s)4( pape)20(r ad)20(dresses i)6(s)4(s)24(ues of w)6(h)20(en an)20(d how)6( w)6(e)0( sh)20(oul)6(d )-20(dev)24(ol)6(ve )-20(aut)22(hori)6(t)2(y)]TJ
+0 -1.14 TD
+0.003 Tc
+0.099 Tw
+[(from )20(ce)19(ntral)5( )20(t)21(o)-1( )20(l)5(o)-1(cal)5( gov)23(ernm)16(ent. It)21( devel)5(o)19(p)-1(s a fr)16(amew)5(o)19(r)-4(k to h)19(e)-1(l)5(p)-1( answ)5(e)19(r the)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(fol)5(l)5(o)-1(w)5(i)5(ng thr)16(ee ques)23(ti)5(ons:)]TJ
+0 -2.32 TD
+0.004 Tc
+(1.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+0.66 0.02 TD
+0.003 Tc
+0.099 Tw
+[(W)7(hat l)5(e)-1(vel)5( of g)19(o)-1(vern)19(ment s)23(houl)5(d m)16(a)-1(ke soci)5(al)5( a)19(nd pol)5(i)5(t)1(i)5(c)3(al)5( )20(deci)5(s)3(i)5(ons )-20(a)19(bout)]TJ
+0.86 -1.16 TD
+0 Tw
+[(pol)4(i)4(cy obj)4(ecti)4(ves?)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+(2.)Tj
+0.84 -0.02 TD
+0 Tc
+( )Tj
+0.66 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(hat l)5(e)-1(vel)5( of g)19(o)-1(vern)19(ment s)23(houl)5(d b)19(ear t)21(he costs o)19(f)1( these d)19(e)-1(ci)5(si)5(ons?)]TJ
+-1.5 -2.32 TD
+0.004 Tc
+(3.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+0.66 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(W)8(hat l)6(e)0(vel)6( of g)20(o)0(vern)20(ment s)24(houl)6(d i)6(m)17(pl)6(emen)20(t the)20(m)-3(?)]TJ
+-1.5 -2.3 TD
+0.138 Tw
+[(The pa)20(per l)6(o)20(oks at dev)24(ol)6(uti)6(on )20(both f)22(r)-3(om )-20(a)20( )-20(gene)20(ral)6( )-20(the)20(o)0(reti)6(cal)6( )-20(s)24(t)2(andp)20(oi)6(nt )-20(and)]TJ
+0 -1.16 TD
+0.158 Tw
+[(from )20(th)20(e per)17(specti)6(ve o)20(f)2( the N)6(e)0(w)6( )20(Zeal)6(a)20(nd R)6(e)0(sou)20(r)-3(ce M)17(anage)20(ment A)11(c)4(t )20(\(R)6(MA)11(\).)]TJ
+T*
+0.002 Tc
+0 Tw
+[(A)9(l)4(though the R)24(M)-5(A)9( is discussed t)20(h)-2(r)-5(o)-2(u)18(ghout, )20(the f)20(r)-5(am)-5(ewo)18(r)-5(k will apply t)20(o)-2( any )-20(a)18(r)-5(ea)]TJ
+T*
+-0.001 Tw
+[(of pol)5(i)5(cy for w)25(h)-1(i)5(c)3(h devol)25(uti)5(on deci)5(s)3(i)5(o)19(ns ar)16(e bei)5(ng c)23(onsi)5(d)-1(e)19(r)-4(ed.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.018 Tw
+[(The R)6(e)0(sou)20(r)-3(ce )20(Manag)20(ement)22( A)11(c)4(t i)6(s)4( based )20(on a ve)20(ry devol)6(v)24(ed fra)20(m)-3(ew)6(o)20(r)-3(k. Th)20(ere)]TJ
+0 -1.16 TD
+0.003 Tc
+0.499 Tw
+[(i)5(s)3( a rol)5(e)-1( fo)19(r nati)5(o)19(nal)5( gove)19(r)-4(nm)16(ent bu)19(t i)5(n)-1( pr)16(acti)5(ce, m)16(o)-1(st deci)5(s)3(i)5(ons)23( )-20(and)]TJ
+T*
+-0.001 Tw
+[(i)5(m)-4(pl)5(ement)21(ati)5(on occ)23(u)-1(rs at )20(regi)5(o)19(nal)5( and l)25(o)-1(cal)5( gove)19(r)-4(nm)16(ent l)5(e)-1(vel)5(.)]TJ
+0 -2.32 TD
+0.079 Tw
+[(D)5(e)-1(vol)5(u)-1(ti)5(on i)5(ssues )20(are co)19(mpl)5(e)-1(x a)19(nd the)19(r)-4(e a)19(r)-4(e sel)5(d)-1(o)19(m)-4( \221)5(p)-1(u)19(r)-4(e\222)5( res)23(u)-1(l)5(t)1(s, pa)19(rti)5(c)3(ul)5(arl)5(y)]TJ
+0 -1.14 TD
+[(i)5(n)-1( )20(the case )20(of such a)19( w)5(i)5(de-)16(rangi)5(ng)19( pol)5(i)5(cy ar)16(ea as )20(resou)19(r)-4(ce ma)19(nage)19(ment. )20(Our)]TJ
+0 -1.16 TD
+0.399 Tw
+[(concl)5(u)-1(si)5(ons ab)19(out the)19( R)5(M)-4(A)10( offe)19(r a mi)5(xt)21(ure o)19(f)1( sol)5(u)-1(ti)5(ons,)21( fro)19(m)-4( )-20(l)5(egi)5(sl)5(ati)5(v)3(e)]TJ
+T*
+0.059 Tw
+[(adj)5(ustments)23( to cha)19(nge th)19(e l)5(e)-1(vel)5( of )20(gover)16(nment)21(, to co)19(mpl)5(e)-1(m)16(entary)23( )-20(pol)5(i)5(c)3(i)5(e)-1(s )-20(th)19(at)]TJ
+T*
+-0.001 Tw
+[(support t)21(he cu)19(rrent)21( struct)21(ures.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.118 Tw
+[(W)8(e)0( )20(regul)6(ate)20( )20(reso)20(urce )20(us)24(e )20(for)17( )20(a nu)20(mber )20(of re)20(asons. W)8(h)20(ere p)20(ubl)6(i)6(c)4( goo)20(ds and)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(commons i)5(s)3(s)23(ues ar)16(e si)5(gni)5(fi)5(cant)21( w)5(e)-1( pr)16(ovi)5(de and)19( pro)19(t)1(ect the)19( )-20(reso)19(urce )-20(t)21(h)-1(roug)19(h)]TJ
+T*
+0.099 Tw
+[(regul)5(ati)5(o)-1(n)19(.)1( W)7(her)16(e exte)19(rnal)5(i)5(t)1(i)5(e)-1(s th)19(at affec)23(t)1( few)5( pe)19(opl)5(e a)19(r)-4(e si)5(gni)5(fi)5(can)19(t, )-20(w)5(e)-1( )-20(m)16(o)-1(st)]TJ
+T*
+0.004 Tc
+0.238 Tw
+[(approp)20(ri)6(atel)6(y p)20(r)-3(ovi)6(de )20(a cl)6(ear )20(defi)6(n)0(i)6(t)2(i)6(on )20(of pr)17(operty)24( )-20(ri)6(ghts and )-20(a process)24( )-20(for)]TJ
+T*
+0.003 Tc
+0.279 Tw
+[(negoti)5(a)-1(ti)5(on)19( )20(and )20(di)5(s)23(pute )40(resol)5(u)-1(ti)5(on)19(. W)7(her)16(e ther)16(e ar)16(e si)5(gni)5(fi)5(cant)21( i)5(n)-1(form)16(ati)5(o)-1(n)]TJ
+0 -1.14 TD
+0.359 Tw
+[(fai)5(l)5(u)-1(res w)5(e)-1( )20(mi)5(ght set )20(and e)19(n)-1(force)19( nati)5(o)-1(n)19(a)-1(l)5( stand)19(ards, )20(and )-20(p)19(r)-4(ovi)5(de )-20(p)19(ubl)5(i)5(c)]TJ
+0 -1.16 TD
+[(educati)5(on.)]TJ
+0 -2.32 TD
+0.079 Tw
+[(The pa)19(per acc)23(epts th)19(at w)5(e)-1( )]TJ
+12 0 2.551 12 249.12 248 Tm
+-0.016 Tc
+[(ar)-23(e)]TJ
+12 0 0 12 266.4 248 Tm
+0.003 Tc
+[( goi)5(n)19(g)-1( to r)16(egul)5(ate)19( reso)19(urce us)23(e and focuses )-20(o)19(n)]TJ
+-13.92 -1.16 TD
+0.219 Tw
+[(the i)5(ssue of )]TJ
+12 0 2.551 12 172.08 234.08 Tm
+0.004 Tc
+(how)Tj
+12 0 0 12 194.16 234.08 Tm
+0.003 Tc
+0.239 Tw
+[( )20(w)5(e)-1( )20(bes)23(t achi)5(eve)19( thi)5(s)3(. In )20(addre)19(ssi)5(ng th)19(e thr)16(ee devol)25(uti)5(o)-1(n)]TJ
+-7.9 -1.14 TD
+0.119 Tw
+[(questi)5(on )20(l)5(i)5(s)3(ted)19( above,)21( the p)19(aper )20(di)5(vi)5(des up)19( anal)5(ysi)5(s i)5(n)-1(to)19( deci)5(s)3(i)5(on )20(maki)5(ng a)19(n)-1(d)]TJ
+0 -1.16 TD
+0.419 Tw
+[(cost )20(beari)5(n)19(g )20(\(secti)25(on 4\))16(, i)5(m)-4(pl)5(e)19(m)-4(entati)25(on \(secti)5(o)19(n)-1( 5\))16( and t)21(he rel)25(a)-1(ti)5(onshi)5(p)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(betw)6(een th)20(e tw)6(o \(s)24(ecti)6(on 6)20(\))-3(. W)8(hat )20(are t)22(he cri)6(t)2(e)20(r)-3(i)6(a)0( fo)20(r devol)26(uti)6(on?)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.005 Tc
+[(S)12(o)-4(cial D)7(ecis)21(i)3(on)16( Maki)23(ng )20(an)16(d C)7(o)-4(s)21(t)-2( B)7(ear)14(in)16(g)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.278 Tw
+[(The p)20(r)-3(obl)6(em)17( w)6(i)6(t)2(h effi)6(ci)6(ent)22( publ)6(i)6(c)4( go)20(od )-20(p)20(r)-3(ovi)6(s)4(i)6(on )-20(i)6(s)4( )-20(th)20(at )-20(the gover)17(nment)22( )-20(i)6(s)]TJ
+0 -1.14 TD
+-0.022 Tw
+[(unabl)6(e )-20(to reveal)6( pri)6(v)4(ate pref)22(erenc)24(es )-20(i)6(n)0( )-20(any exact )-20(m)17(anne)20(r.)]TJ
+ET
+endstream endobj 134 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 135 0 obj << /Length 6707 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(4)Tj
+-34.86 58.98 TD
+0.004 Tc
+0.058 Tw
+[(P)11(eopl)6(e )20(reveal)6( )40(thei)6(r )40(prefe)20(r)-3(ences )20(thro)20(ugh tw)6(o i)6(m)17(perf)22(e)0(ct mec)24(hani)6(sms:)22( voti)6(ng w)6(i)6(t)2(h)]TJ
+0 -1.16 TD
+0.002 Tc
+0.62 Tw
+[(their)-5( feet)20( \()-5(T)-7(i)24(ebout )20(m)-5(odel )20(of m)-5(obility)22(\))-5( and )-20(s)22(o)-2(cial )-20(choice m)-5(e)-2(cha)18(n)-2(ism)-5(s)]TJ
+T*
+0.419 Tw
+[(\(i)5(nvol)5(veme)19(nt i)5(n)-1( pol)5(i)5(t)1(i)5(c)3(al)5( )20(process)23(e)-1(s\). W)7(e)-1( c)23(oncent)21(rate p)19(r)-4(i)5(m)-4(a)19(r)-4(i)5(l)5(y)3( on )-20(soci)5(al)]TJ
+T*
+-0.001 Tw
+[(deci)5(s)3(i)5(on maki)5(n)19(g)-1( proc)23(esses.)]TJ
+0 -2.3 TD
+0.499 Tw
+[(D)5(oes )20(devol)5(uti)5(o)19(n i)5(m)-4(pr)16(ove soci)5(al)5( c)23(hoi)5(ce m)16(e)-1(chani)5(sms)23( and l)5(e)19(ad to b)19(e)-1(tter)]TJ
+0 -1.16 TD
+0.004 Tc
+0.298 Tw
+[(prefer)17(ence )20(r)17(e)0(vel)6(a)0(ti)6(on)20(? )20( W)8(e)0( hav)24(e i)6(denti)6(f)2(i)6(e)20(d thre)20(e pri)26(n)0(ci)6(pl)6(es and)20( cri)6(t)2(e)20(r)-3(i)6(a)0( for)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(deci)5(d)-1(i)5(ng w)5(hen)19( devol)5(uti)5(o)19(n of d)19(e)-1(ci)5(si)5(on m)16(a)-1(ki)5(ng i)5(s)3( ap)19(prop)19(ri)5(ate.)]TJ
+12 0 2.551 12 99.36 621.2 Tm
+0.004 Tc
+-0.002 Tw
+[(1)-1800(I)2(nform)17(ed deci)6(s)4(i)6(o)0(n)20(-maki)6(n)20(g)0(.)]TJ
+12 0 0 12 99.36 595.28 Tm
+0.003 Tc
+0.099 Tw
+[(The )20(best)21( )20(deci)5(s)3(i)5(ons )40(refl)5(ect )40(al)5(l)5( the r)16(e)-1(l)5(e)-1(vant s)23(ubj)5(ecti)5(ve a)19(nd obj)5(ecti)5(v)23(e)-1( i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)19(.)]TJ
+T*
+0.119 Tw
+[(Those w)5(h)-1(o)19( expe)19(ri)5(ence th)19(e effec)23(t)1(s shoul)5(d make )-20(t)21(he )-20(deci)5(s)3(i)5(o)19(ns, )-20(si)5(nce )-20(i)5(t)1( )-20(i)5(s)3( )-20(t)21(hey)]TJ
+T*
+0.14 Tw
+[(who have su)18(bjective p)18(r)-5(efer)15(ences a)18(bout th)18(e issue. P)9(e)-2(o)18(p)-2(le with )-20(th)18(e )-20(skills )-20(and)]TJ
+T*
+[(resourc)23(e)-1(s to access)23( obj)5(ecti)5(ve i)25(n)-1(for)16(m)-4(ati)5(on sh)19(oul)5(d al)5(so)19( be i)5(n)-1(vol)5(v)3(e)19(d)-1( i)5(n)-1( )-20(deci)5(s)3(i)5(o)19(n)]TJ
+0 -1.14 TD
+[(maki)5(ng.)]TJ
+12 0 2.551 12 99.36 512 Tm
+-0.001 Tw
+[(2)-1801(B)10(al)5(anced deci)5(s)3(i)5(on )20(maki)5(ng.)]TJ
+12 0 0 12 99.36 486.08 Tm
+0.159 Tw
+[(If peopl)5(e w)5(i)5(t)1(hi)25(n the j)5(u)19(ri)5(sdi)5(c)3(ti)5(on t)21(hat m)16(a)-1(kes the )-20(d)19(e)-1(ci)5(si)5(on )-20(b)19(ear )-20(al)5(l)5( benefi)5(t)1(s and)]TJ
+0 -1.16 TD
+0.219 Tw
+[(costs, ther)16(e are)19( no i)5(n)-1(te)19(rj)5(uri)5(s)3(di)5(cti)25(onal)5( exte)19(rnal)5(i)5(t)1(i)5(e)-1(s t)21(hat )-20(coul)25(d )-20(l)5(ead )-20(t)21(o)-1( )-20(over)16( )-20(or)]TJ
+0 -1.14 TD
+0.259 Tw
+[(under)16(-provi)5(si)5(o)19(n)-1( )20(of )20(th)19(e )20(publ)5(i)5(c)3( )20(g)19(ood. D)5(e)-1(ci)5(si)5(o)19(n)-1(s shoul)5(d)19( ther)16(efore)19( be l)5(o)-1(ca)19(ted,)]TJ
+0 -1.16 TD
+0.179 Tw
+[(w)5(here )20(possi)25(bl)5(e, )20(w)5(i)5(t)1(h )20(th)19(e )20(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( of eff)21(e)-1(cts and)19( costs. P)10(eopl)25(e w)5(ho m)16(a)-1(ke)]TJ
+T*
+-0.001 Tw
+[(deci)5(s)3(i)5(ons shoul)5(d)19( be th)19(ose w)5(ho )20(recei)5(v)3(e )20(benefi)5(t)1(s, )20(and b)19(ear cos)23(t)1(s.)]TJ
+12 0 2.551 12 99.36 402.8 Tm
+0 Tw
+[(3)-1802(C)4(ost effecti)4(v)2(e d)18(e)-2(ci)4(si)4(on m)15(a)-2(ki)4(ng)]TJ
+12 0 0 12 99.36 377.12 Tm
+0.004 Tc
+0.398 Tw
+[(W)8(here )20(costs )20(of deci)6(s)4(i)6(on )20(maki)6(ng )20(are hi)26(gh an)20(d pref)22(erenc)24(es ar)17(e rel)6(a)0(ti)6(v)24(e)0(l)6(y)]TJ
+T*
+0.003 Tc
+0.239 Tw
+[(homoge)19(neous, )20(nati)5(onal)5( )20(pol)5(i)5(c)3(i)5(e)-1(s can s)23(a)-1(ve consi)5(d)19(erabl)5(y )20(on du)19(pl)5(i)5(c)3(ati)5(on costs.)]TJ
+T*
+0.199 Tw
+[(The )20(l)5(o)-1(cati)5(o)19(n)-1( )20(of )20(d)19(e)-1(ci)5(si)5(on m)16(a)-1(ki)5(ng mus)23(t)1( be i)5(n)-1(f)21(o)-1(rm)16(ed by co)19(nsi)5(dera)19(t)1(i)5(ons of c)23(o)-1(st)]TJ
+T*
+(effectiveness.)Tj
+0 -2.3 TD
+0.004 Tc
+0.198 Tw
+[(The )20(Ti)26(ebout )40(model)6( s)24(uggests t)22(hat havi)26(ng mul)6(t)2(i)6(p)0(l)26(e)0( j)6(u)0(ri)6(sdi)6(c)4(ti)6(o)20(n)0(s i)6(s)4( val)6(u)0(a)20(b)0(l)6(e)0( for)]TJ
+0 -1.16 TD
+0.002 Tc
+0.06 Tw
+[(better)-5( )20(r)-5(e)-2(flecting)18( hete)18(r)-5(ogen)18(eous p)18(r)-5(efe)18(r)-5(ences and )-20(im)15(pr)-5(oving account)20(ability. )-20( )-20(T)13(h)-2(e)]TJ
+T*
+0 Tc
+0.002 Tw
+[(p)-4(o)-4(ssib)-4(ility o)-4(f)-2( m)-7(o)16(b)-4(ility m)-7(a)-4(ke)-4(s it)18( m)-7(o)-4(r)13(e)-4( im)-7(p)-4(o)16(r)-7(t)-2(a)-4(n)-4(t)-2( t)18(o)-4( m)-7(a)16(tch)-4( co)-4(sts a)16(n)-4(d)-4( b)-4(e)16(n)-4(e)-4(f)-2(its )-20(with)-4(i)2(n)]TJ
+T*
+0.002 Tc
+0.1 Tw
+[(a )20(jur)-5(i)4(sdiction )20(s)22(o)-2( )20(that )40(people )20(c)22(annot )40(avoid costs w)24(h)-2(ile still r)-5(e)-2(ceivin)18(g bene)18(fits by)]TJ
+T*
+0 Tc
+0.002 Tw
+[(m)-7(o)-4(vin)-4(g)-4( o)-4(u)-4(t)18( o)-4(f)-2( th)16(e)-4( ju)-4(r)-7(i)2(sd)-4(ictio)16(n)-4(. M)-7(o)16(b)-4(ility a)-4(l)2(so)-4( h)-4(a)-4(s)20( )-20(im)-7(p)-4(lica)-4(t)-2(io)-4(n)-4(s)20( )-20(fo)-4(r)-7( )-20(t)18(h)-4(e)-4( )-20(g)-4(o)-4(v)20(e)-4(r)-7(n)-4(m)13(e)-4(n)-4(t)]TJ
+0 -1.14 TD
+0.003 Tc
+0.019 Tw
+[(rol)5(e)-1( at th)19(e l)5(o)-1(cal)5( l)5(e)-1(vel)5(.)21( Local)5( g)19(o)-1(vern)19(ments )-20(c)23(annot effecti)5(v)3(el)5(y redi)5(stri)25(bute )-20(i)5(n)-1(co)19(me)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(w)6(i)6(t)2(hout i)6(nduci)6(n)20(g out)22(-mi)6(gr)17(ati)6(on by )20(ri)6(ch pe)20(opl)6(e an)20(d i)6(n)0(-mi)26(grati)6(o)20(n by th)20(e poo)20(r.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.005 Tc
+[(Im)14(plem)14(enta)21(tio)16(n)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+0.219 Tw
+[(W)7(e)-1( defi)5(ne i)5(m)16(pl)5(ement)21(ati)5(on as)23( )-20(acti)5(vi)5(ti)5(es )-20(ai)5(m)16(ed )-20(at achi)5(evi)5(ng )-20(n)19(on-di)5(sc)23(reti)5(on)19(ary)]TJ
+0 -1.16 TD
+0.099 Tw
+[(goal)5(s )20(set by s)23(o)-1(ci)5(al)5( deci)5(s)3(i)5(o)-1(n)19(-make)19(rs. )20(The r)16(e)-1(l)5(a)-1(ti)5(ve adv)23(antag)19(e of ce)19(ntral)5( ve)19(rsus)]TJ
+0 -1.14 TD
+0.399 Tw
+[(l)5(o)-1(cal)5( i)5(m)-4(pl)5(eme)19(n)-1(ters )20(depen)19(ds heavi)5(l)5(y)3( o)19(n)-1( )-20(the bal)5(ance betw)5(een)19( )-20(l)5(o)-1(cal)5(l)5(y)3( )-20(and)]TJ
+0 -1.16 TD
+0.259 Tw
+[(central)5(l)5(y)3( hel)25(d i)5(n)-1(for)16(m)-4(ati)5(on.)21( Local)5( g)19(o)-1(vern)19(ment c)23(an m)16(o)-1(st easi)5(l)5(y)3( )-20(access)23( )-20(l)5(o)-1(cal)]TJ
+T*
+0.004 Tc
+0.198 Tw
+[(i)6(n)0(formati)26(on, )20(such )40(as )20(mo)20(ni)6(tori)6(ng)20( of co)20(mpl)6(i)6(ance a)20(nd know)6(l)6(e)20(dge of)22( speci)6(a)0(l)6(i)6(s)4(ed)]TJ
+ET
+endstream endobj 136 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 137 0 obj << /Length 6584 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(5)Tj
+-34.86 58.98 TD
+0.003 Tc
+0.239 Tw
+[(condi)5(ti)5(ons. G)21(ener)16(al)5( techni)5(cal)5( i)5(n)19(form)16(ati)5(on )20(may be )20(most )-20(av)23(ai)5(l)5(abl)5(e )-20(to )-20(c)23(entral)]TJ
+0 -1.16 TD
+0.004 Tc
+[(govern)20(m)-3(ent.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.039 Tw
+[(E)10(c)3(onomi)5(e)-1(s )20(of )20(scal)25(e)-1( may l)5(e)19(ad to i)25(m)-4(pl)5(em)16(entati)5(o)-1(n)19( bei)5(ng )20(achi)5(eved )20(most ef)21(fi)5(ci)5(entl)5(y)]TJ
+0 -1.14 TD
+-0.001 Tc
+0.263 Tw
+[(a)-5(t)-3( th)-5(e)-5( ce)-5(n)15(t)-3(r)-8(a)-5(l le)-5(ve)-5(l.)17( F)-10(o)15(r)-8( o)-5(t)-3(h)-5(e)15(r)-8( a)-5(c)-1(tivitie)-5(s)-1( wh)15(e)-5(r)-8(e)-5( )-20(fl)21(e)-5(x)-1(ib)-5(ility )-20(is )-20(im)-8(p)-5(o)15(r)-8(t)-3(a)-5(n)-5(t, )-20(l)21(o)-5(ca)-5(l)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(i)6(m)-3(pl)6(ement)22(ati)6(on )20(may be )20(more)20( effecti)6(v)4(e)20(.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+[(S)11(e)0(p)-5(a)0(r)13(a)0(b)-5(ilit)17(y o)15(f)-3( Im)13(p)-5(l)2(em)13(en)15(tati)22(o)-5(n)-5( )20(fr)13(o)-5(m)13( Decisio)15(n)-5(-M)17(aki)22(n)-5(g)15(?)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+-0.001 Tw
+[(H)5(o)-1(w)5( shoul)5(d the)19( contr)16(a)-1(ct be w)25(r)-4(i)5(tten b)19(e)-1(tw)5(een th)19(e )-20(pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(on-m)16(a)-1(ke)19(r )-20(and )-20(t)21(h)-1(e)]TJ
+0 -1.16 TD
+0.459 Tw
+[(i)5(m)-4(pl)5(ement)21(er i)5(f)1( t)21(hey ar)16(e not t)21(he sam)16(e? C)5(l)5(e)-1(a)19(r)-4( obj)5(ecti)5(v)23(e)-1(s )-20(and )-20(l)5(i)5(n)19(es )-20(of)]TJ
+0 -1.14 TD
+0.18 Tw
+[(accountability a)18(r)-5(e ess)22(ential. Howev)22(e)-2(r)-5(,)0( this )-20(c)22(an )-20(be difficult )-20(to achieve )-20(in the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(case of an )20(arms l)26(ength c)24(ontrac)24(t)2( betw)6(e)20(en centr)17(a)0(l)6( an)20(d l)6(o)0(cal)6( )-20(gov)24(ernm)17(ent. )-20( The)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(rel)5(a)-1(ti)5(ve )20(adv)23(antag)19(es )20(of )20(th)19(e di)5(ffe)19(rent p)19(o)-1(tenti)5(a)-1(l)5( de)19(ci)5(si)5(on m)16(a)-1(kers a)19(nd i)5(m)-4(pl)25(ement)21(ers)]TJ
+T*
+0.299 Tw
+[(shoul)5(d be w)5(e)-1(i)25(ghed a)19(gai)5(nst t)21(he deg)19(ree )20(of di)5(ffi)5(cul)5(t)1(y i)5(n)-1( )-20(c)23(ontr)16(a)-1(cti)5(ng )-20(be)19(fore a)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(deci)6(s)4(i)6(on i)6(s)4( ma)20(de to se)20(para)20(t)2(e deci)6(s)4(i)6(o)0(n)20(-maki)6(n)20(g)0( fro)20(m)-3( i)6(m)-3(pl)6(e)20(m)-3(ent)22(ati)6(on.)]TJ
+/F3 1 Tf
+0 -2.62 TD
+0.003 Tc
+-0.001 Tw
+[(Acco)-6(u)14(n)-6(ta)19(b)-6(ilit)16(y o)-6(f)16( Go)-6(v)19(e)-1(r)12(n)-6(m)12(e)-1(n)-6(t)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.298 Tw
+[(W)8(hen w)6(e)0( have )20(deci)6(ded )20(the m)17(o)0(st app)20(rop)20(r)-3(i)6(a)0(te p)20(o)0(l)6(i)6(t)2(i)6(c)4(al)6( deci)6(s)4(i)6(on )20(maker)17( )-20(and)]TJ
+0 -1.16 TD
+0.002 Tc
+0.14 Tw
+[(im)-5(plem)-5(ent)20(er)-5(, )20(we )40(need )20(t)20(o)-2( conside)18(r)-5( how t)20(h)-2(is fits with th)18(e cur)15(r)-5(ent acc)22(ounta)18(b)-2(ility)]TJ
+0 -1.14 TD
+0.004 Tc
+0.418 Tw
+[(structur)17(e. )20( )20(T)15(he )20(ques)24(ti)6(on i)6(s)4( w)6(het)22(her l)6(o)0(c)24(a)0(l)6( or cen)20(t)2(ral)6( )20(govern)20(m)-3(ent )20(pol)6(i)6(t)2(i)6(c)4(al)]TJ
+0 -1.16 TD
+0.002 Tc
+0.24 Tw
+[(structur)15(es )20(are)18( )20(mor)15(e)-2( )20(accou)18(n)-2(table f)20(o)-2(r political )20(decisions. )20(If, for)15( exam)15(ple, we)]TJ
+T*
+0.339 Tw
+[(consi)5(der )20(l)5(o)-1(c)23(a)-1(l)5( )20(gover)16(nmen)19(t to be)19( l)5(e)-1(ss accou)19(n)-1(tabl)5(e, w)25(e)-1( may )20(prefe)19(r)-4( centr)16(a)-1(l)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(i)6(m)-3(pl)6(ement)22(ati)6(on d)20(e)0(spi)6(t)2(e th)20(e othe)20(r adva)20(n)0(tages)24( of l)6(o)0(cal)6( g)20(o)0(vern)20(ment.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.006 Tc
+[(S)13(o)-3(ver)15(eign)17(ty)]TJ
+/F5 1 Tf
+0 -2.14 TD
+0.003 Tc
+0.179 Tw
+[(C)5(onversel)5(y)3(, )20(i)5(n)-1( )20(s)23(p)-1(i)5(t)1(e )20(of t)21(he m)16(any ar)16(gume)19(n)-1(ts i)5(n)-1( favo)19(ur of)21( centr)16(a)-1(l)5(i)5(s)3(ed deci)5(s)3(i)5(o)19(n)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.043 Tw
+[(m)-8(a)-5(kin)-5(g)-5( a)-5(n)15(d)-5( im)-8(p)-5(l)1(e)15(m)-8(e)-5(n)-5(t)-3(a)-5(t)-3(i)21(o)-5(n)-5( we)-5( m)12(a)-5(y still b)-5(i)1(a)-5(s)-1( to)-5(wa)15(r)-8(d)-5( d)15(e)-5(vo)-5(lvin)-5(g)-5( d)15(e)-5(cisio)-5(n)-5( )-20(m)-8(a)-5(ki)21(n)-5(g)]TJ
+T*
+0.003 Tc
+0.339 Tw
+[(to l)5(o)-1(cal)5( com)16(m)-4(uni)5(ti)5(es i)5(f)1( t)21(he soci)5(al)5( i)25(m)-4(port)21(ance of)21( l)5(o)-1(cal)5( i)5(den)19(ti)5(ty and c)23(ontrol)]TJ
+T*
+-0.001 Tw
+[(outw)5(e)-1(i)5(ghs th)19(e soci)5(al)5( choi)5(c)23(e)-1( and )20(effi)5(ci)5(ency ben)19(efi)5(t)1(s of)21( mor)16(e)-1( cent)21(ral)5(i)5(s)3(ed co)19(ntrol)5(.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.006 Tc
+-0.004 Tw
+[(Fr)15(am)15(ewor)15(k for)15( A)8(n)-3(a)22(l)4(ysis )20(of D)8(e)22(vol)24(u)-3(ti)24(on)]TJ
+/F5 1 Tf
+0 -2.14 TD
+0.004 Tc
+0.078 Tw
+[(Fi)6(gure )40(1 )20(gi)6(ves )20(a )20(s)24(t)2(yl)6(i)6(s)4(ed re)20(prese)20(n)0(tati)6(on )20(of the d)20(i)6(ffer)17(ent deci)6(s)4(i)6(o)20(ns and )20(trade)20(offs)]TJ
+0 -1.16 TD
+0.003 Tc
+0.239 Tw
+[(di)5(scussed abov)23(e. T)14(he box)23(es on th)19(e ri)5(gh)19(t rep)19(r)-4(esent)21( the f)21(a)-1(cts rel)5(a)19(ti)5(ng to a)]TJ
+T*
+-0.001 Tw
+[(speci)5(f)1(i)5(c)3( i)5(ssue, the)19( i)5(m)-4(po)19(rtance )20(of )-20(di)5(ffe)19(rent )-20(ty)23(pes )-20(of )-20(i)5(n)19(form)16(ati)5(on )-20(a)19(nd )-20(thei)25(r )-20(l)5(o)-1(cati)5(o)19(n)-1(.)]TJ
+T*
+0.24 Tw
+[(T)-7(he ellipses )20(on the)18( left r)-5(e)18(pr)-5(ese)18(n)-2(t decisio)18(n nodes)22(. Im)-5(pl)24(em)-5(ent)20(ation, )-20(p)18(o)-2(litical)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(deci)6(s)4(i)6(ons, and)20( cost be)20(ari)6(ng c)24(an be )20(born)20(e)0( )-20(i)6(n)0( )-20(di)6(ffe)20(rent \223l)6(ocati)6(ons)24(\224, )-20(i)6(e)0(. di)6(ffere)20(nt)]TJ
+0 -1.14 TD
+0.003 Tc
+0.179 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(ons )20(o)19(r)-4( )20(l)5(e)-1(vel)5(s)3( )20(of )20(gover)16(nment)21(. Matc)23(hes i)5(n)-1( te)19(rms o)19(f)1( l)5(o)-1(cati)5(on)19(, betw)5(e)-1(e)19(n)]TJ
+0 -1.16 TD
+0.3 Tw
+[(ellipses, and b)18(e)-2(tween )20(ellipses and)18( boxes g)18(ener)15(ate be)18(nefits, m)-5(o)-2(r)-5(e)-2( efficient)]TJ
+T*
+0.579 Tw
+[(i)5(m)-4(pl)5(ement)21(ati)5(on, )20(reduce)19(d)-1( cont)21(racti)5(ng )20(di)5(ffi)5(cul)5(t)1(i)5(e)-1(s, m)16(o)-1(re bal)5(anced)19( )-20(deci)5(s)3(i)5(o)-1(n)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(maki)6(ng, an)20(d mo)20(re eq)20(ui)6(tabl)6(e cos)24(t)2( bea)20(ri)6(ng.)]TJ
+ET
+endstream endobj 138 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 139 0 obj << /Type /Page /Parent 123 0 R /Resources 141 0 R /Contents 140 0 R >> endobj 140 0 obj << /Length 8494 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(6)Tj
+/F3 1 Tf
+-34.86 58.96 TD
+0.007 Tc
+-0.005 Tw
+[(Fi)5(gur)16(e )20(1 D)9(e)3(v)23(o)-2(l)5(u)-2(t)20(i)5(on)18( Fr)16(am)16(ew)5(or)16(k)]TJ
+ET
+0 0 0 RG
+0 J 0 j 1.92 w 10 M []0 d
+1 i
+396.72 602 141.36 -21.36 re
+S
+BT
+/F5 1 Tf
+11.76 0 0 11.76 409.44 588.797 Tm
+0.001 Tw
+[(Su)12(b)-8(j)5(e)12(c)17(ti)5(v)17(e)-8( i)25(n)-8(fo)12(r)14(m)3(a)12(t)-1(i)5(o)12(n)]TJ
+ET
+396.72 545.36 56.64 -21.12 re
+S
+BT
+11.76 0 0 11.76 403.68 532.397 Tm
+0.006 Tc
+[(Be)11(n)-9(e)11(fit)19(s)]TJ
+ET
+312.24 644.24 70.56 -49.44 re
+S
+BT
+11.76 0 0 11.76 322.8 631.037 Tm
+-0.001 Tc
+[(Ob)-16(j)17(e)-16(c)9(t)-9(iv)9(e)]TJ
+-0.4082 -1.1633 TD
+0.008 Tc
+[(In)13(fo)13(r)-6(m)25(a)-7(t)21(i)6(o)-7(n)]TJ
+0.3673 -1.1633 TD
+0.003 Tc
+0.005 Tw
+[(a)8(n)-12(d)8( Sk)13(ills)]TJ
+ET
+1 J 1 j
+446.16 580.64 m
+432.24 545.36 l
+S
+BT
+11.76 0 0 11.76 108.48 554.477 Tm
+0.004 Tc
+[(Po)9(lit)-4(i)22(c)-6(a)9(l)]TJ
+T*
+-0.009 Tc
+[(De)-24(ci)-11(s)-19(i)9(o)-24(n)]TJ
+ET
+0.72 w
+163.8 549.2 m
+163.8 549.2 l
+163.8 562.779 149.554 573.8 132 573.8 c
+114.446 573.8 100.2 562.779 100.2 549.2 c
+100.2 535.621 114.446 524.6 132 524.6 c
+149.554 524.6 163.8 535.621 163.8 549.2 c
+h
+163.92 538.4 m
+396.72 538.4 l
+S
+BT
+9.84 0 0 9.84 200.16 541.88 Tm
+0.005 Tc
+-0.015 Tw
+[(D)20(e)0(c)-7(i)32(s)-7(i)7(o)24(n)0(s)17( )-25(r)21(e)0(f)15(l)7(ec)17(t)15( )-25(s)17(o)0(c)17(i)7(al)7( p)24(r)-3(ef)15(er)21(en)24(c)-7(e)24(s)]TJ
+11.76 0 0 11.76 242.4 427.517 Tm
+-0.009 Tc
+[(Co)-24(st)]TJ
+T*
+0.004 Tc
+[(Be)9(a)-11(r)10(in)]TJ
+ET
+q
+242.4 412.16 47.76 26.4 re
+W n
+BT
+11.76 0 0 11.76 276.477 413.837 Tm
+0 Tc
+0 Tw
+(g)Tj
+ET
+Q
+297.72 422 m
+297.72 422 l
+297.72 435.645 281.968 446.72 262.56 446.72 c
+243.152 446.72 227.4 435.645 227.4 422 c
+227.4 408.355 243.152 397.28 262.56 397.28 c
+281.968 397.28 297.72 408.355 297.72 422 c
+h
+248.64 446.72 m
+163.92 531.44 l
+S
+BT
+9.84 0 0 9.84 108.48 499.64 Tm
+-0.002 Tc
+[(A)6(c)-14(c)10(o)-7(u)17(n)-7(t)8(a)-7(b)17(ilit)8(y)]TJ
+0 -1.1951 TD
+-0.011 Tc
+0.001 Tw
+[(to)-16( ta)-16(x )-25(p)8(a)-16(ye)-16(r)-19(s)]TJ
+2.8537 -2.3902 TD
+-0.019 Tc
+0.521 Tw
+[(A)-11(v)-31(oi)-17(d \223)-27(u)-24(nf)-9(u)-24(n)0(d)-24(e)-24(d)]TJ
+0 -1.1951 TD
+0.005 Tc
+[(m)9(a)24(nd)24(at)15(es)-7(\224)]TJ
+ET
+403.92 524.24 m
+290.88 439.52 l
+S
+BT
+9.84 0 0 9.84 362.4 478.28 Tm
+0.01 Tw
+[(F)6(i)7(s)17(c)-7(al)32( E)13(q)24(ui)32(v)-7(a)0(l)32(enc)17(e)]TJ
+T*
+-0.016 Tw
+[(N)21(o)1( re)25(di)8(s)18(t)-9(r)22(i)8(bu)25(t)-9(i)33(on)]TJ
+11.76 0 0 11.76 164.88 695.597 Tm
+-0.005 Tc
+[(I)-13(m)12(p)-20(l)-7(em)-9(en)-20(t)8(a)-20(t)-13(i)13(o)-20(n)]TJ
+ET
+248.28 700.88 m
+248.28 700.88 l
+248.28 712.538 227.797 722 202.56 722 c
+177.323 722 156.84 712.538 156.84 700.88 c
+156.84 689.222 177.323 679.76 202.56 679.76 c
+227.797 679.76 248.28 689.222 248.28 700.88 c
+h
+241.68 686.72 m
+319.2 644.24 l
+248.64 707.84 m
+403.92 686.72 l
+S
+BT
+9.84 0 0 9.84 299.04 661.88 Tm
+-0.009 Tc
+-0.001 Tw
+[(Effi)-7(c)-21(i)-7(e)10(n)-14(t Pr)-17(o)-14(v)3(i)-7(s)-21(i)18(o)-14(n)]TJ
+ET
+213.12 679.76 m
+213.6 679.52 l
+212.88 678.8 l
+212.64 679.04 l
+213.12 679.76 l
+f*
+211.44 677.6 m
+211.92 677.12 l
+211.44 676.4 l
+210.96 676.64 l
+211.44 677.6 l
+f*
+209.76 675.2 m
+210.24 674.96 l
+209.76 674.24 l
+209.28 674.48 l
+209.76 675.2 l
+f*
+208.08 672.8 m
+208.56 672.56 l
+208.08 671.84 l
+207.6 672.08 l
+208.08 672.8 l
+f*
+206.4 670.64 m
+206.88 670.4 l
+206.4 669.44 l
+205.92 669.92 l
+206.4 670.64 l
+f*
+204.72 668.48 m
+205.2 668 l
+204.72 667.28 l
+204.24 667.76 l
+204.72 668.48 l
+f*
+203.04 666.08 m
+203.52 665.84 l
+203.04 664.88 l
+202.56 665.36 l
+203.04 666.08 l
+f*
+201.36 663.68 m
+201.84 663.44 l
+201.36 662.72 l
+200.88 662.96 l
+201.36 663.68 l
+f*
+199.68 661.52 m
+200.16 661.28 l
+199.68 660.56 l
+199.2 660.8 l
+199.68 661.52 l
+f*
+198 659.36 m
+198.48 658.88 l
+198 658.16 l
+197.52 658.4 l
+198 659.36 l
+f*
+196.32 656.96 m
+196.8 656.72 l
+196.32 656 l
+195.84 656.24 l
+196.32 656.96 l
+f*
+194.88 654.8 m
+195.12 654.32 l
+194.64 653.6 l
+194.16 653.84 l
+194.88 654.8 l
+f*
+193.2 652.4 m
+193.68 652.16 l
+192.96 651.2 l
+192.48 651.68 l
+193.2 652.4 l
+f*
+191.28 650.24 m
+191.76 649.76 l
+191.28 649.04 l
+190.8 649.52 l
+191.28 650.24 l
+f*
+189.6 647.84 m
+190.08 647.6 l
+189.6 646.64 l
+189.12 647.12 l
+189.6 647.84 l
+f*
+188.16 645.44 m
+188.64 645.2 l
+187.92 644.48 l
+187.44 644.96 l
+188.16 645.44 l
+f*
+186.48 643.28 m
+186.96 643.04 l
+186.24 642.32 l
+185.76 642.56 l
+186.48 643.28 l
+f*
+184.56 640.88 m
+185.04 640.64 l
+184.56 639.92 l
+184.08 640.16 l
+184.56 640.88 l
+f*
+183.12 638.72 m
+183.36 638.48 l
+183.12 637.76 l
+182.64 638 l
+183.12 638.72 l
+f*
+181.44 636.56 m
+181.92 636.08 l
+181.2 635.36 l
+180.72 635.6 l
+181.44 636.56 l
+f*
+179.76 634.16 m
+180.24 633.92 l
+179.52 633.2 l
+179.04 633.44 l
+179.76 634.16 l
+f*
+178.08 632 m
+178.56 631.52 l
+177.84 630.8 l
+177.36 631.28 l
+178.08 632 l
+f*
+176.4 629.6 m
+176.88 629.36 l
+176.4 628.4 l
+175.92 628.64 l
+176.4 629.6 l
+f*
+174.72 627.44 m
+175.2 626.96 l
+174.72 626.24 l
+174.24 626.72 l
+174.72 627.44 l
+f*
+173.04 625.04 m
+173.52 624.8 l
+172.8 624.08 l
+172.32 624.32 l
+173.04 625.04 l
+f*
+171.36 622.88 m
+171.84 622.4 l
+171.36 621.68 l
+170.88 621.92 l
+171.36 622.88 l
+f*
+169.68 620.48 m
+170.16 620.24 l
+169.68 619.52 l
+169.2 619.76 l
+169.68 620.48 l
+f*
+168 618.08 m
+168.48 617.84 l
+168 617.12 l
+167.52 617.36 l
+168 618.08 l
+f*
+166.32 615.92 m
+166.8 615.68 l
+166.08 614.96 l
+165.6 615.2 l
+166.32 615.92 l
+f*
+164.64 613.76 m
+165.12 613.28 l
+164.64 612.56 l
+164.16 613.04 l
+164.64 613.76 l
+f*
+162.96 611.36 m
+163.44 611.12 l
+162.96 610.16 l
+162.48 610.64 l
+162.96 611.36 l
+f*
+161.28 609.2 m
+161.76 608.72 l
+161.28 608 l
+160.8 608.48 l
+161.28 609.2 l
+f*
+159.6 606.8 m
+160.08 606.56 l
+159.6 605.84 l
+159.12 606.08 l
+159.6 606.8 l
+f*
+157.92 604.64 m
+158.4 604.16 l
+157.92 603.44 l
+157.44 603.92 l
+157.92 604.64 l
+f*
+156.24 602.24 m
+156.72 602 l
+156.24 601.28 l
+155.76 601.52 l
+156.24 602.24 l
+f*
+154.56 600.08 m
+155.04 599.6 l
+154.56 598.88 l
+154.08 599.36 l
+154.56 600.08 l
+f*
+153.12 597.92 m
+153.36 597.44 l
+152.88 596.72 l
+152.4 596.96 l
+153.12 597.92 l
+f*
+151.2 595.52 m
+151.68 595.04 l
+151.2 594.32 l
+150.72 594.8 l
+151.2 595.52 l
+f*
+149.52 593.12 m
+150 592.88 l
+149.52 592.16 l
+149.04 592.4 l
+149.52 593.12 l
+f*
+147.84 590.96 m
+148.32 590.48 l
+147.84 589.76 l
+147.36 590.24 l
+147.84 590.96 l
+f*
+146.4 588.56 m
+146.88 588.32 l
+146.16 587.6 l
+145.68 587.84 l
+146.4 588.56 l
+f*
+144.72 586.4 m
+145.2 586.16 l
+144.48 585.2 l
+144 585.68 l
+144.72 586.4 l
+f*
+142.8 584 m
+143.28 583.76 l
+142.8 583.04 l
+142.32 583.28 l
+142.8 584 l
+f*
+141.36 581.84 m
+141.6 581.36 l
+141.12 580.64 l
+140.64 581.12 l
+141.36 581.84 l
+f*
+139.68 579.68 m
+140.16 579.2 l
+139.44 578.48 l
+138.96 578.72 l
+139.68 579.68 l
+f*
+138 577.28 m
+138.48 576.8 l
+137.76 576.08 l
+137.28 576.56 l
+138 577.28 l
+f*
+136.32 574.88 m
+136.8 574.64 l
+136.08 573.92 l
+135.6 574.16 l
+136.32 574.88 l
+f*
+BT
+9.84 0 0 9.84 143.76 647.72 Tm
+0.005 Tc
+[(S)13(e)24(par)21(ab)24(l)7(e)0(?)]TJ
+ET
+0.96 w
+312.24 602 m
+163.92 559.52 l
+S
+BT
+9.84 0 0 9.84 164.88 598.28 Tm
+-0.01 Tc
+[(In)-15(fo)-15(r)6(m)-6(e)-15(d)]TJ
+T*
+0.012 Tc
+-0.022 Tw
+[(d)7(e)31(ci)39(si)14(o)31(n)7( m)16(a)7(k)24(i)14(n)7(g)]TJ
+3.5854 -5.9756 TD
+-0.002 Tc
+-0.008 Tw
+[(A)6(v)-14(o)17(i)0(d)17( )-25(in)17(t)8(e)-7(r)-10(j)25(u)-7(r)-10(is)10(d)-7(i)25(c)-14(t)8(io)-7(n)17(a)-7(l e)17(x)-14(t)8(e)-7(r)-10(n)17(a)-7(l)25(it)-17(i)25(e)-7(s)]TJ
+ET
+0 J 0 j 1.92 w
+403.92 693.68 127.2 -35.52 re
+S
+BT
+11.76 0 0 11.76 424.08 680.477 Tm
+0.009 Tc
+-0.001 Tw
+[(Ph)14(ys)19(i)7(c)-1(a)14(l)7( E)23(ffe)14(ct)22(s:)]TJ
+-1.3061 -1.1633 TD
+0.007 Tc
+0.001 Tw
+[(Mo)12(n)-8(i)25(to)-8(r)13(i)25(n)-8(g)12( In)12(fo)12(r)-7(m)24(a)-8(t)20(i)5(o)-8(n)]TJ
+ET
+99.36 722.96 0.72 -0.72 re
+f*
+99.36 722.96 0.72 -0.72 re
+f*
+100.08 722.96 438.96 -0.72 re
+f*
+539.04 722.96 0.72 -0.72 re
+f*
+539.04 722.96 0.72 -0.72 re
+f*
+99.36 722.24 0.72 -325.44 re
+f*
+539.04 722.24 0.72 -325.44 re
+f*
+99.36 396.8 0.72 -0.72 re
+f*
+99.36 396.8 0.72 -0.72 re
+f*
+100.08 396.8 438.96 -0.72 re
+f*
+539.04 396.8 0.72 -0.72 re
+f*
+539.04 396.8 0.72 -0.72 re
+f*
+BT
+10.08 0 0 10.08 99.36 353.735 Tm
+0 Tc
+0 Tw
+( )Tj
+ET
+endstream endobj 141 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 142 0 obj << /Length 7480 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(7)Tj
+/F3 1 Tf
+-34.86 58.94 TD
+-0.001 Tc
+[(1)-1805(I)-3(NT)-10(RODUCT)-10(ION)]TJ
+12 0 2.551 12 99.36 719.6 Tm
+0.004 Tc
+-0.002 Tw
+[(D)6(evolu)15(tio)15(n)-5( an)15(d d)15(ece)20(ntr)13(a)0(lisa)20(t)-3(io)15(n)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 693.085 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 693.44 Tm
+0.003 Tc
+-0.001 Tw
+[(D)5(e)-1(vol)5(u)-1(ti)5(on i)5(s)3( defi)25(ned as t)21(he tr)16(ansfe)19(r of au)19(thori)5(t)1(y )20(from)16( a hi)5(gh)19(er to )20(a l)5(o)-1(w)5(e)-1(r l)25(e)-1(vel)5( )-20(of)]TJ
+0 -1.16 TD
+0.004 Tc
+0.158 Tw
+[(govern)20(m)-3(ent. )20( )40(The )40(obj)6(ecti)6(ve of)22( thi)6(s)4( pap)20(er i)6(s)4( to)20( establ)6(i)6(s)4(h c)24(r)-3(i)6(t)2(eri)6(a)20( for w)6(h)20(en thi)6(s)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(shoul)5(d occu)19(r. W)7(hen s)23(houl)5(d w)5(e)-1( )20(devol)5(ve )20(authori)25(t)1(y to r)16(egul)5(ate)19( )-20(exter)16(nal)5(i)5(t)1(i)5(e)-1(s )-20(an)19(d)]TJ
+T*
+-0.001 Tw
+[(publ)5(i)5(c)3( goods )20(from)16( centr)16(a)-1(l)5( to l)5(o)-1(cal)5( )20(gover)16(nment?)]TJ
+10.08 0 0 10.08 99.36 637.645 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 624.08 Tm
+0.004 Tc
+-0.002 Tw
+[(In consi)6(deri)26(ng dev)24(ol)6(uti)6(on, t)22(here )20(are t)22(h)0(ree )20(questi)6(on)20(s that )20(need t)22(o)0( be a)20(n)0(sw)6(ered)20(.)]TJ
+10.08 0 0 10.08 99.36 609.805 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 596.24 Tm
+0.004 Tc
+(1.)Tj
+0.84 -0.02 TD
+0 Tc
+( )Tj
+0.66 0.02 TD
+0.003 Tc
+0.099 Tw
+[(W)7(hat l)5(e)-1(vel)5( of g)19(o)-1(vern)19(ment s)23(houl)5(d m)16(a)-1(ke soci)5(al)5( a)19(nd pol)5(i)5(t)1(i)5(c)3(al)5( )20(deci)5(s)3(i)5(ons )-20(a)19(bout)]TJ
+0.86 -1.16 TD
+0 Tw
+[(pol)4(i)4(cy obj)4(ecti)4(ves?)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+(2.)Tj
+0.84 -0.02 TD
+0 Tc
+( )Tj
+0.66 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(hat l)5(e)-1(vel)5( of g)19(o)-1(vern)19(ment s)23(houl)5(d b)19(ear t)21(he costs o)19(f)1( these )20(deci)5(s)3(i)5(ons?)]TJ
+-1.5 -2.32 TD
+0.004 Tc
+(3.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+0.66 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(W)8(hat l)6(e)0(vel)6( of g)20(o)0(vern)20(ment s)24(houl)6(d i)6(m)17(pl)6(emen)20(t the)20(m)-3(?)]TJ
+10.08 0 0 10.08 99.36 512.605 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3571 TD
+( )Tj
+12 0 0 12 99.36 499.28 Tm
+0.004 Tc
+0.198 Tw
+[(D)6(e)0(vol)6(u)0(ti)6(on of )20(autho)20(ri)6(ty must)22( be consi)26(dere)20(d)0( toget)22(her )-20(w)6(i)6(t)2(h)20( )-20(argu)20(ments for )-20(a)20(n)0(d)]TJ
+0 -1.16 TD
+0.058 Tw
+[(agai)6(nst dec)24(entral)6(i)6(s)4(a)20(t)2(i)6(on of i)26(m)-3(pl)6(eme)20(n)0(tati)6(on)20(. D)6(e)0(cent)22(ral)6(i)6(s)4(ati)6(on c)24(an be defi)6(ned)20( )-20(as)]TJ
+T*
+0.158 Tw
+[(the use of)22( a l)6(o)0(w)6(e)0(r)17( l)6(e)0(vel)6( of g)20(o)0(vern)20(ment )20(as an i)6(m)17(pl)6(eme)20(n)0(ti)6(ng ag)20(ent fo)20(r cent)22(ral)]TJ
+T*
+0.002 Tc
+0.14 Tw
+[(gover)-5(n)18(m)-5(ent p)18(o)-2(licy. In a )20(pur)-5(e )20(decent)20(r)-5(a)-2(lised syst)20(em)-5(, local )20(gover)15(nm)-5(en)18(t )-20(m)-5(e)18(r)-5(e)-2(ly)]TJ
+T*
+0.004 Tc
+0.038 Tw
+[(carri)6(es o)20(u)0(t the i)6(n)0(s)24(t)2(ructi)6(o)20(ns of cen)20(t)2(ral)6( g)20(o)0(vern)20(ment i)6(n)20( )-20(a )-20(non)20(-di)6(scre)20(t)2(i)6(onary)24( )-20(w)6(a)0(y. )-20(In)]TJ
+0 -1.14 TD
+0.003 Tc
+0.319 Tw
+[(real)5(i)5(t)1(y )20(these)19( )20(are )40(not usu)19(a)-1(l)5(l)5(y)3( cl)5(earl)5(y)3( di)5(s)23(t)1(i)5(ngui)5(she)19(d)-1(. N)5(e)-1(ve)19(rthel)5(ess, t)21(hey a)19(r)-4(e)]TJ
+0 -1.16 TD
+0.119 Tw
+[(conceptual)5(l)5(y)3( di)5(sti)25(n)-1(ct and )20(to un)19(dersta)19(nd the)19( )-20(opti)5(m)-4(al)5( al)5(l)5(o)-1(cati)5(on of )-20(aut)21(hori)5(t)1(y )-20(a)19(n)-1(d)]TJ
+T*
+0.08 Tw
+[(r)-5(e)-2(sponsibility )20(a)18(nd the)18( tr)-5(ad)18(eoffs involv)22(ed in choo)18(sing th)18(em)-5(, we )20(m)-5(u)-2(st ke)18(ep the)18(m)]TJ
+T*
+-0.001 Tw
+[(cl)5(earl)5(y)3( sepa)19(rate i)5(n)-1( )20(our )20(anal)5(ysi)5(s.)]TJ
+10.08 0 0 10.08 99.36 373.885 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3571 TD
+( )Tj
+12 0 0 12 99.36 360.56 Tm
+0.004 Tc
+0.398 Tw
+[(Many )20(past )40(and p)20(o)0(tenti)6(a)0(l)6( N)6(e)0(w)6( )20(Zeal)6(a)20(nd r)17(e)0(for)17(m)-3(s i)6(n)0(vol)6(v)4(e a c)24(o)0(mbi)6(n)20(ati)6(on of)]TJ
+0 -1.16 TD
+0.158 Tw
+[(devol)6(uti)6(on a)20(nd dec)24(entral)6(i)6(s)4(a)20(t)2(i)6(on. In)20( parti)6(c)24(u)0(l)6(a)0(r )-20(th)20(e )-20(R)6(e)0(sou)20(r)-3(ce )-20(Ma)20(nage)20(ment )-20(A)11(c)4(t)]TJ
+T*
+0.118 Tw
+[(\(R)6(MA)11(\), the )20(heal)6(th )20(and ed)20(ucati)6(on )20(refo)20(rms, a)20(nd deci)6(s)4(i)6(o)20(ns abou)20(t )-20(the )-20(i)6(n)0(s)24(t)2(i)6(t)2(uti)6(ons)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(for )20(add)19(ressi)5(ng )40(Maori)5( i)5(s)3(s)23(ues hav)23(e l)5(ed to si)25(gni)5(fi)5(cant )20(devol)5(uti)5(o)-1(n)19( of aut)21(hori)5(t)1(y.)]TJ
+T*
+0.004 Tc
+0.398 Tw
+[(E)11(m)-3(pl)6(oyment )20(pol)6(i)6(cy and s)24(o)0(ci)6(al)6( w)6(e)0(l)6(f)2(ar)17(e are)20( areas)24( w)6(here)20( devol)6(uti)26(on i)6(s)4( )-20(an)]TJ
+0 -1.14 TD
+0.003 Tc
+0.259 Tw
+[(i)5(m)-4(porta)19(nt )20(pol)5(i)5(cy )20(op)19(ti)5(on. )20(The )20(rol)5(e)-1( an)19(d functi)5(o)19(n)-1( of l)5(o)-1(cal)5( )20(gover)16(nment)21( i)5(s)3( al)5(so)]TJ
+0 -1.16 TD
+0.299 Tw
+[(i)5(nherentl)5(y)3( )40(an i)5(ssue )20(of the )20(appr)16(opri)5(a)-1(te)19( l)5(e)-1(vel)5( of d)19(e)-1(vol)5(u)-1(ti)5(on)19(. Ma)19(ny of th)19(ese)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(refor)17(m)-3(s )20(have )40(now)6( )20(bee)20(n )20(i)6(n)0( )20(pl)6(ace)20( )20(for )40(a )20(num)17(ber o)20(f)2( years)24(,)2( so i)6(t)2( i)6(s)4( a)20(pprop)20(ri)6(ate t)22(o)]TJ
+T*
+0.003 Tc
+0.239 Tw
+[(revi)5(ew)5( our)16( expe)19(ri)5(ence of)21( devol)5(uti)5(o)19(n, i)5(den)19(ti)5(fy the succ)23(esses, an)19(d atte)19(mpt )-20(to)]TJ
+T*
+-0.001 Tw
+[(address t)21(he pr)16(obl)5(ems )20(that h)19(a)-1(ve ari)5(s)23(en.)]TJ
+10.08 0 0 10.08 99.36 221.485 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 207.92 Tm
+0.003 Tc
+0.179 Tw
+[(The )20(i)5(ssues )20(i)25(n)-1(vol)5(v)3(ed )20(i)5(n)-1( )20(devol)5(uti)5(o)-1(n)19( are c)23(o)-1(mpl)5(e)-1(x.)21( D)5(i)5(ffere)19(nt publ)5(i)5(c)3( )20(good i)5(ssu)19(es)]TJ
+0 -1.16 TD
+0.099 Tw
+[(have )20(di)5(ffe)19(rent ch)19(aracte)19(ri)5(sti)5(cs that)21( l)5(ead t)21(o)-1( di)5(ffere)19(nt o)19(p)-1(ti)5(mal)5( pol)5(i)5(cy s)23(t)1(ructu)19(r)-4(es. A)]TJ
+T*
+0.079 Tw
+[(case by case )20(anal)5(ysi)5(s i)5(s)3( re)19(qui)5(re)19(d. N)5(e)-1(ve)19(rthel)5(ess, w)5(e)19( )-20(hope that )-20(w)5(e)-1( are )-20(a)19(b)-1(l)5(e)-1( )-20(to)]TJ
+T*
+0.299 Tw
+[(uncover g)19(ener)16(al)5( pri)5(n)-1(ci)5(pl)25(es to hel)25(p gui)5(de)19( us )-20(i)5(n)-1( )-20(m)16(a)-1(ki)5(ng )-20(sensi)25(b)-1(l)5(e)-1( )-20(devol)5(u)19(t)1(i)5(o)-1(n)]TJ
+0 -1.14 TD
+[(deci)5(s)3(i)5(ons.)]TJ
+10.08 0 0 10.08 99.36 138.205 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 124.64 Tm
+0.004 Tc
+0.158 Tw
+[(Thi)6(s)4( )20(pape)20(r ad)20(dresses )20(the i)6(ssue )20(of dev)24(ol)6(uti)6(on b)20(o)0(th fr)17(om a )20(gene)20(ral)6( theo)20(reti)6(cal)]TJ
+0 -1.16 TD
+0.003 Tc
+0.679 Tw
+[(standpoi)5(nt )40(and )20(f)21(r)-4(om )20(t)21(he )20(pe)19(rspecti)5(ve )40(of the N)25(e)-1(w)5( Zeal)25(and R)5(e)-1(so)19(urce)]TJ
+T*
+0.119 Tw
+[(Manage)19(ment A)10(c)3(t. A)10(ppl)5(yi)25(ng the)19(o)-1(reti)5(cal)5( )20(pri)5(n)-1(ci)5(pl)5(es i)5(n)19( a pa)19(rti)5(c)3(ul)5(ar )20(pol)5(i)5(cy contex)23(t)]TJ
+ET
+endstream endobj 143 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 144 0 obj << /Length 8641 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(8)Tj
+-34.86 58.98 TD
+0.004 Tc
+0.038 Tw
+[(through)20(out th)20(e pap)20(er hel)26(ps make )20(the d)20(e)0(vel)6(opi)6(ng )20(fram)17(ew)6(ork )20(more c)24(oncre)20(te )-20(and)]TJ
+0 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(tests its pr)-6(incipl)23(es.)]TJ
+10.08 0 0 10.08 99.36 717.805 Tm
+0 Tc
+0 Tw
+( )Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 704.24 Tm
+0.007 Tc
+-0.005 Tw
+[(The R)9(e)23(sour)16(ce)23( Ma)23(nagem)16(e)23(nt A)9(c)23(t)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 677.725 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 678.08 Tm
+0.004 Tc
+0.098 Tw
+[(The R)6(e)0(sou)20(r)-3(ce )20(Manag)20(ement)22( A)11(c)4(t 1991 i)6(s)4( t)22(he )-20(pri)26(n)0(ci)6(pal)6( )-20(l)6(egi)6(sl)6(ati)6(o)20(n )-20(gove)20(r)-3(ni)6(ng )-20(t)22(h)0(e)]TJ
+T*
+0.002 Tc
+0.06 Tw
+[(use of New )20(Z)-7(ealand\222s l)24(and, ai)24(r, wate)18(r, ecosyste)18(m)-5(s, soils, geology and )-20(th)18(e )-20(built)]TJ
+T*
+0.159 Tw
+[(envi)5(r)-4(onm)16(ent. It)21( al)5(so cont)21(rol)5(s)3( noi)5(s)23(e)-1(, pol)5(l)5(u)-1(ti)5(o)19(n)-1( and )20(geoth)19(e)-1(rmal)5( )20(acti)5(vi)5(ti)5(es. )-20( The)]TJ
+0 -1.14 TD
+0.004 Tc
+0.258 Tw
+[(R)6(M)-3(A)11( i)6(n)0(tegrat)22(ed res)24(ource )20(and e)20(n)0(vi)6(ron)20(m)-3(ental)6( m)17(ana)20(gemen)20(t )-20(by )-20(co)20(mbi)6(n)0(i)6(ng )-20(5)20(9)]TJ
+0 -1.16 TD
+0.003 Tc
+0.139 Tw
+[(separate)19( )20(statut)21(es. )20( )20(A)10( )20(ful)5(l)5(e)-1(r )20(descri)5(p)-1(ti)5(o)19(n)-1( of th)19(e maj)5(o)19(r fea)19(t)1(ures )20(of the R)25(M)-4(A)10(,)1( and)]TJ
+T*
+-0.001 Tw
+[(w)5(hat i)5(t)1( repl)5(a)19(c)3(ed, i)5(s)3( co)19(ntai)5(ned i)25(n)-1( A)10(ppendi)5(x O)21(ne.)]TJ
+10.08 0 0 10.08 99.36 594.445 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3809 TD
+( )Tj
+12 0 0 12 99.36 580.88 Tm
+0.004 Tc
+0.318 Tw
+[(The R)6(M)-3(A)11( i)6(s)4( bas)24(ed on )20(a very )20(devol)6(ved )20(fram)17(ew)6(ork. )-20( )-20(A)11( )-20(ce)20(ntral)6( )-20(u)20(nderl)6(y)4(i)6(n)20(g)]TJ
+0 -1.14 TD
+0.003 Tc
+0.439 Tw
+[(assumpti)5(on i)5(s)23( that g)19(o)-1(verni)25(ng bodi)25(es cl)5(osest to )20(reso)19(urces )-20(a)19(r)-4(e )-20(th)19(e )-20(most)]TJ
+0 -1.16 TD
+0.004 Tc
+0.078 Tw
+[(approp)20(ri)6(ate t)22(o)0( gove)20(r)-3(n the)20( use of )20(those )20(resou)20(r)-3(ces. A)11(l)6(thou)20(gh a )20(rol)6(e)0( )-20(fo)20(r )-20(nati)6(o)20(nal)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(govern)19(m)-4(ent i)5(s)3( sp)19(eci)5(f)1(i)5(ed, i)5(n)-1( )20(practi)5(ce, )20(most d)19(e)-1(ci)5(si)5(ons an)19(d i)5(m)-4(pl)5(e)19(m)-4(entati)25(on )-20(occu)19(r)]TJ
+T*
+0.004 Tc
+0.038 Tw
+[(at )20(the )20(l)6(e)0(vel)6( )40(of )20(re)20(gi)6(onal)6( )20(an)20(d )20(l)6(o)0(cal)6( gov)24(ern)20(m)-3(ent. R)26(e)0(sourc)24(e)0( man)20(agem)17(ent r)17(e)0(for)17(m)-3( i)6(n)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(N)5(e)-1(w)5( Zeal)5(an)19(d w)5(a)-1(s rel)5(a)19(ted to)19( l)5(o)-1(cal)5( gove)19(r)-4(nm)16(ent )-20(r)16(e)-1(for)16(m)-4(. )-20( )-20(T)14(he )-20(Local)5( Gover)16(n)-1(ment)]TJ
+0 -1.14 TD
+0.004 Tc
+0.038 Tw
+[(A)11(c)4(t 1989 l)6(a)0(i)6(d)0( th)20(e foun)20(dati)6(on f)22(o)0(r th)20(e am)17(al)6(gamati)26(on )-20(of over )-20(8)20(00 )-20(l)6(o)0(cal)6( )-20(a)20(u)0(thori)6(t)2(i)26(e)0(s,)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(boards, )20(boro)19(ughs etc i)25(n)-1(to th)19(e 86 l)5(o)-1(cal)5( )20(autho)19(ri)5(ti)5(es exi)5(s)3(ti)5(ng)19( curr)16(entl)5(y)3(.)]TJ
+10.08 0 0 10.08 99.36 469.645 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 456.08 Tm
+0.004 Tc
+-0.002 Tw
+[(The R)6(M)-3(A)11( has)24( been )20(pro)20(m)-3(oted i)6(n)20(tern)20(ati)6(onal)6(l)6(y)4( as )20(a l)6(eadi)6(n)20(g)0( exam)17(pl)6(e of )-20(i)6(n)0(t)22(egra)20(t)2(ed,)]TJ
+0 -1.16 TD
+0.003 Tc
+0.259 Tw
+[(enl)5(i)5(ghtene)19(d reso)19(urce )20(manag)19(emen)19(t. Its st)21(ructur)16(e cont)21(rasts si)5(gni)5(fi)5(c)23(antl)5(y)3( w)5(i)5(t)1(h)]TJ
+0 -1.14 TD
+0.04 Tw
+[(systems such )20(as that in)18( the Unite)18(d)-2( S)9(t)0(ates )-20(th)18(at )-20(com)15(b)-2(ines )-20(fe)18(deral and )-20(stat)20(e, )-20(an)18(d)]TJ
+0 -1.16 TD
+0.099 Tw
+[(w)5(i)5(t)1(h many E)10(u)-1(r)16(opean sys)23(tems t)21(hat )-20(ar)16(e )-20(heavi)5(l)5(y)3( )-20(n)19(a)-1(ti)5(onal)5( and )-20(to a )-20(cert)21(ai)5(n )-20(exte)19(nt)]TJ
+0 -1.26 TD
+0.004 Tc
+0.198 Tw
+[(E)11(u)0(rope-w)6(i)6(d)0(e)20( thro)20(ugh th)20(e E)11(C)6(.)]TJ
+10.08 0 0 10.08 261.36 402.445 Tm
+0 Tc
+0 Tw
+(1)Tj
+12 0 0 12 266.88 399.44 Tm
+0.004 Tc
+0.218 Tw
+[( U)6(nders)24(t)2(andi)6(ng)20( the e)20(ffects of N)26(e)0(w)6( Zeal)26(and's)]TJ
+-13.96 -1.16 TD
+-0.002 Tw
+[(chosen fo)20(rm of )20(regul)26(ati)6(on has)24( i)6(m)-3(pl)6(i)6(c)4(ati)6(ons)24( w)6(i)6(t)2(hi)6(n an)20(d beyon)20(d N)6(e)0(w)6( Z)15(eal)6(and.)]TJ
+10.08 0 0 10.08 99.36 371.485 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 357.92 Tm
+0.004 Tc
+0.078 Tw
+[(A)11(s)4( )20(menti)6(oned )40(above, )20(ther)17(e are)20( no easy)24( answ)6(e)0(rs)24( to dev)24(ol)6(uti)6(on q)20(uesti)6(ons. )20( The)]TJ
+0 -1.16 TD
+0.003 Tc
+0.539 Tw
+[(R)5(M)-4(A)10( covers such )20(a w)5(i)5(de r)16(ange )20(of i)5(ssues w)5(i)5(t)1(h di)25(ffere)19(nt )-20(geo)19(grap)19(hi)5(cal)]TJ
+T*
+0.579 Tw
+[(bounda)19(ri)5(es, an)19(d varyi)5(n)-1(g)19( l)5(e)-1(vel)5(s)3( of sci)5(e)19(n)-1(ti)5(fi)5(c )-20(com)16(p)-1(l)5(e)-1(xi)5(ty )-20(and pref)21(erenc)23(e)]TJ
+T*
+0.06 Tw
+[(heter)-5(og)18(eneity t)20(hat we will not )20(em)-5(e)18(r)-5(ge with )20(one \221pu)18(r)-5(e\222 r)-5(e)-2(s)22(u)-2(lt. New )20(Z)-7(ealand)18( is )-20(a)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(very smal)5(l)5( co)19(untry )20(and can)19(not ho)19(pe to )20(perfec)23(t)1(l)5(y)3( sol)5(v)3(e eac)23(h i)5(ssue se)19(parat)21(el)5(y.)]TJ
+10.08 0 0 10.08 99.36 288.205 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3809 TD
+( )Tj
+12 0 0 12 99.36 274.64 Tm
+0.003 Tc
+0.059 Tw
+[(W)7(i)5(th )20(regar)16(d )20(to th)19(e R)5(M)-4(A)10(,)1( i)5(n)-1( so)19(me cases)23( the cur)16(r)-4(en)19(t l)5(e)-1(vel)5( of )20(devol)5(uti)5(o)19(n, and )20(the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.158 Tw
+[(concomi)6(t)2(ant)22( )20(fundi)6(n)20(g)0( )20(and i)26(m)-3(pl)6(em)17(entati)6(o)20(n struct)22(ures, c)24(r)-3(eates)24( seri)6(ous)24( probl)26(ems)]TJ
+T*
+0.058 Tw
+[(that )20(nee)20(d )20(to )20(be)20( )20(add)20(ressed by)24( changi)6(n)20(g)0( the l)26(e)0(vel)6( of g)20(o)0(vern)20(ment t)22(hat ad)20(dresses)]TJ
+0 -1.14 TD
+0.003 Tc
+0.059 Tw
+[(the )20(i)5(ssue. H)5(o)-1(w)5(e)-1(v)23(e)-1(r, t)21(h)-1(i)5(s)3( pape)19(r concl)5(u)19(des that )20(the ov)23(eral)5(l)5( i)5(n)-1(sti)5(t)1(u)19(t)1(i)5(onal)5( st)21(ructur)16(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.158 Tw
+[(i)6(s)4( broadl)6(y a)20(ppro)20(p)0(ri)6(ate )20(for co)20(re l)6(a)0(n)20(d)0( use, )20(bui)6(l)6(t)2( envi)6(r)17(onme)20(n)0(t and )20(ai)6(r an)20(d w)6(a)0(te)20(r)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(qual)5(i)5(t)1(y i)5(ssues. I)21(n)-1( many)23( othe)19(r cases n)19(o)-1( opti)25(m)-4(al)5(, pr)16(obl)5(em)16(-free)19( struct)21(ure exi)5(s)3(ts)23(, )-20(or)]TJ
+T*
+0.039 Tw
+[(that achi)5(evi)5(n)19(g i)5(t)1( w)5(oul)5(d d)19(a)-1(mag)19(e)-1( )-20(the )-20(c)23(ohesi)5(on )-20(o)19(f)1( )-20(the overal)5(l)5( regul)5(a)19(t)1(ory )-20(st)21(ructur)16(e.)]TJ
+T*
+0.339 Tw
+[(In these cas)23(e)-1(s w)5(e)-1( can i)25(denti)5(f)1(y t)21(he i)5(nevi)5(t)1(a)19(b)-1(l)5(e)-1( confl)5(i)5(c)3(ts )20(and p)19(r)-4(obl)5(ems)23( and)]TJ
+0 -1.14 TD
+0.479 Tw
+[(propose )20(pol)5(i)5(c)3(i)5(e)-1(s com)16(p)-1(l)5(e)-1(me)19(ntary t)21(o)-1( the R)25(M)-4(A)10( to enco)19(u)-1(rag)19(e)-1( )-20(the )-20(fl)25(ow)5( )-20(of)]TJ
+0 -3.18 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 129.68 m
+99.366 129.68 l
+S
+BT
+12 0 0 12 200.16 125.6 Tm
+( )Tj
+ET
+243.843 129.68 m
+200.163 129.68 l
+S
+BT
+10.08 0 0 10.08 99.36 113.725 Tm
+0 Tc
+(1)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.135 Tw
+[( )-1857(T)-16(he US)-8( s)16(y)-8(s)-8(t)-16(em)15( c)-8(o)0(m)-8(bines)-8( a )24(f)-16(eder)-8(al agenc)-8(y)-8(,)-16( t)-16(he E)-8(n)0(v)-8(i)0(r)-8(onm)-8(ent)-16(al P)-8(r)-8(o)0(t)-16(e)0(c)-8(t)-16(ion )-24(A)-8(genc)-8(y)16(,)-16( )-24(and)]TJ
+2.2619 -1.1667 TD
+[(nat)-16(ional env)-8(ir)-8(onm)-8(ent)-16(al legis)-32(lat)-16(ion s)-8(u)0(c)-8(h)0( as)-8( t)-16(he Clean A)-8(i)0(r)-8( A)-8(c)16(t)-16( and Clean W)-17(a)24(t)-16(e)0(r)-8( A)-8(c)16(t)-16(,)8( wit)-16(h)]TJ
+0 -1.1429 TD
+0.016 Tw
+[(im)-8(plem)-8(ent)-16(at)-16(ion at)-16( s)-8(e)0(v)-8(e)0(r)-8(al lev)-8(els)-8(,)-16( s)16(t)-16(at)-16(e,)8( r)-8(egion,)-16( and loc)-8(al c)-8(o)0(m)-8(m)-8(unit)-16(y)-8(.)]TJ
+ET
+endstream endobj 145 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 146 0 obj << /Length 7324 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(9)Tj
+-34.86 58.98 TD
+0.002 Tc
+0.3 Tw
+[(infor)-5(m)-5(a)-2(ti)24(on, skills and )20(r)-5(e)-2(sou)18(r)-5(ces, )20(r)-5(educe)18( duplicatio)18(n of eff)20(o)-2(r)-5(t, and )-20(im)15(pr)-5(ove)]TJ
+0 -1.16 TD
+0 Tw
+[(accountability a)18(nd coo)18(per)-5(ati)24(on.)]TJ
+10.08 0 0 10.08 99.36 717.805 Tm
+0 Tc
+( )Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 704.24 Tm
+0.007 Tc
+-0.005 Tw
+[(A)9(i)5(m)16(s)3( and s)23(t)0(r)16(u)-2(ct)20(ur)16(e of )20(thi)25(s)3( pa)23(per)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 677.725 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 678.08 Tm
+0.003 Tc
+0.039 Tw
+[(The )20(pa)19(per p)19(r)-4(ovi)5(des )20(a met)21(hodol)5(o)19(g)-1(y to an)19(al)5(yse devol)25(uti)5(on, b)19(o)-1(th i)5(n)-1( t)21(he conte)19(x)3(t of)]TJ
+T*
+0.219 Tw
+[(the R)5(M)-4(A)10(,)1( and )20(any oth)19(e)-1(r d)19(e)-1(vol)5(v)3(ed a)19(r)-4(eas )-20(o)19(f)1( )-20(gove)19(r)-4(nme)19(n)-1(t )-20(busi)5(n)19(ess, )-20(actual)5( or)]TJ
+T*
+0.039 Tw
+[(propose)19(d)-1(. )20( )20(T)14(he )20(me)19(thodol)5(o)19(g)-1(y can b)19(e)-1( used)19( to assess )20(the success)23(es and)19( fai)5(l)5(u)-1(res)]TJ
+0 -1.14 TD
+0.159 Tw
+[(of devol)5(uti)5(o)19(n to da)19(te, to i)25(denti)5(f)1(y o)19(p)-1(ti)5(ons fo)19(r pol)5(i)5(cy )-20(r)16(e)-1(for)16(m)-4( )-20(and)19( )-20(to )-20(an)19(al)5(yse )-20(the)]TJ
+0 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(likely effects of a)17(n)-3(y pote)17(n)-3(tial policy )20(r)-6(e)-3(for)14(m)-6(s.)]TJ
+10.08 0 0 10.08 99.36 608.365 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 594.8 Tm
+0.003 Tc
+0.219 Tw
+[(S)10(e)-1(cti)5(on )20(tw)5(o )20(of )20(th)19(e pap)19(er di)5(scuss)23(es the j)5(u)-1(sti)5(f)1(i)5(c)3(a)19(t)1(i)5(on fo)19(r gove)19(r)-4(nm)16(ent\222)5(s)3( rol)25(e)-1( i)5(n)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(regul)6(ati)6(n)0(g)20( )20(w)6(here)20( )20(ther)17(e )20(ar)17(e exter)17(nal)6(i)6(t)2(i)6(e)0(s, p)20(ubl)6(i)6(c)4( goods)24( and i)6(n)0(f)22(o)0(rm)17(ati)6(on fai)6(l)6(u)20(res.)]TJ
+0 -1.14 TD
+0.198 Tw
+[(For th)20(ose exte)20(rnal)6(i)6(t)2(i)6(e)0(s t)22(hat gov)24(ern)20(m)-3(ent d)20(oes deci)6(d)20(e to di)26(rectl)6(y)4( r)17(egul)6(ate,)22( )-20(the)]TJ
+0 -1.16 TD
+0.058 Tw
+[(questi)6(on of)22( how)6( to )20(regul)6(a)20(t)2(e re)20(mai)6(n)0(s. )20(Of par)17(ti)6(cul)6(a)0(r i)6(n)0(t)22(e)0(rest i)26(n)0( )-20(thi)6(s)4( )-20(pa)20(per )-20(i)6(s)4( )-20(h)20(o)0(w)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(the )-20(l)5(e)-1(vel)5( )-20(of gover)16(nment that makes )-20(an)19(d )-20(i)5(m)-4(pl)5(em)16(ents deci)5(s)3(i)5(ons )-20(af)21(fects )-20(the)]TJ
+T*
+-0.001 Tw
+[(choi)5(ces mad)19(e)-1(, and)19( thei)5(r )20(effi)5(ci)5(ency a)19(nd fai)5(r)16(ness.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.158 Tw
+[(There)20( are t)22(h)0(ree)20( essenti)6(a)0(l)6( i)6(s)4(s)24(ues that)22( have t)22(o)0( be co)20(nfron)20(t)2(ed i)6(n)0( )20(maki)6(ng p)20(o)0(l)6(i)6(c)4(y)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(about th)19(e effi)5(ci)5(ent )20(regul)25(ati)5(on of )20(exter)16(nal)5(i)5(t)1(i)5(e)-1(s and)19( publ)5(i)5(c)3( g)19(oods.)]TJ
+0 -2.32 TD
+0.004 Tc
+(1.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+0.319 Tw
+[(S)10(o)-1(ci)5(al)5( and pol)5(i)5(t)1(i)5(c)3(al)5( d)19(e)-1(ci)5(si)5(ons nee)19(d to b)19(e)-1( )-20(made)19( )-20(abo)19(ut )-20(w)5(hat )-20(s)23(o)-1(ci)5(ety\222)5(s)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(obj)5(ecti)5(ves shoul)25(d be. W)7(h)19(at i)5(s)3( the )20(opti)5(m)-4(al)5( l)25(e)-1(vel)5( of p)19(ubl)5(i)5(c)3( goods)23(?)]TJ
+-2.36 -2.4 TD
+0.004 Tc
+(2.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(C)6(o)0(sts need t)22(o)0( be b)20(o)0(rne )20(appr)17(opri)6(a)0(t)22(e)0(l)6(y)4(.)]TJ
+10.08 0 0 10.08 328.32 416.365 Tm
+0 Tc
+0 Tw
+(2)Tj
+12 0 0 12 99.36 385.52 Tm
+0.004 Tc
+(3.)Tj
+0.84 -0.02 TD
+0 Tc
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(D)5(e)-1(ci)5(si)5(ons need t)21(o)-1( be i)25(m)-4(pl)5(eme)19(n)-1(ted a)19(nd obj)5(ec)23(ti)5(ves achi)5(ev)23(ed effi)5(ci)5(en)19(tl)5(y.)]TJ
+-2.36 -2.3 TD
+0.099 Tw
+[(For e)19(a)-1(ch of t)21(hese fu)19(ncti)5(ons w)5(e)-1( )20(need t)21(o)-1( consi)5(d)-1(e)19(r)-4( w)5(h)-1(i)5(c)3(h l)5(e)-1(vel)5( )20(of gov)23(ernm)16(ent i)5(s)]TJ
+0 -1.16 TD
+0.179 Tw
+[(best equi)5(p)19(ped to c)23(a)-1(rry )20(them )20(out. W)7(h)-1(o)19( shoul)5(d )-20(m)16(a)-1(ke )-20(t)21(he )-20(pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(ons?)]TJ
+T*
+-0.001 Tw
+[(W)7(ho shoul)5(d b)19(ear t)21(he costs? )20( W)7(ho sho)19(u)-1(l)5(d)-1( i)5(m)-4(pl)5(e)19(m)-4(ent?)]TJ
+0 -2.3 TD
+0.039 Tw
+[(The choi)5(ce)19( may b)19(e)-1( betw)5(e)19(en seve)19(ral)5( l)5(e)-1(vel)5(s)3( o)19(f)1( gove)19(r)-4(nme)19(n)-1(t \226 th)19(e )-20(R)5(M)-4(A)10( )-20(has rol)5(e)-1(s)]TJ
+0 -1.16 TD
+0.259 Tw
+[(for cent)21(ral)5(,)1( r)16(egi)5(onal)5( a)19(nd di)5(st)21(ri)5(ct bodi)5(es.)21( Our )20(anal)5(ysi)5(s )-20(si)5(mpl)5(i)5(f)1(i)5(e)-1(s)23( )-20(thi)5(s)3( )-20(i)5(n)-1(to a)]TJ
+T*
+0.079 Tw
+[(di)5(scussi)5(on of ce)19(ntral)5( vs. l)25(o)-1(cal)5( )-20(gove)19(r)-4(nm)16(ent. )-20( The )-20(a)19(r)-4(gum)16(ents )-20(an)19(d )-20(pri)5(n)-1(ci)25(pl)5(es )-20(can)]TJ
+T*
+0.259 Tw
+[(be )20(appl)5(i)5(ed )40(to )20(a )40(more )40(mul)5(t)1(i)5(-)-4(ti)5(e)19(r)-4(ed )20(st)21(ructu)19(r)-4(e beca)19(u)-1(se w)5(e)-1( u)19(n)-1(cover)16( cri)5(t)1(eri)25(a)-1( for)]TJ
+T*
+-0.001 Tw
+[(deci)5(d)-1(i)5(ng the)19( opti)5(m)16(al)5( l)5(e)-1(vel)5( of g)19(o)-1(vern)19(ment.)]TJ
+0 -2.3 TD
+0.199 Tw
+[(In addr)16(essi)5(ng th)19(e thre)19(e devol)25(uti)5(on qu)19(esti)5(ons l)5(i)5(s)3(ted)19( above)19(,)1( the p)19(aper)16( )-20(di)5(vi)5(des)]TJ
+0 -1.16 TD
+0.139 Tw
+[(anal)5(ysi)5(s i)5(n)-1(to deci)5(s)3(i)5(o)19(n-m)16(a)-1(ki)5(ng an)19(d cost b)19(eari)5(n)-1(g)19(,)1( i)5(m)-4(pl)5(e)19(m)-4(entati)5(o)19(n, an)19(d )-20(then the)]TJ
+T*
+-0.001 Tw
+[(rel)5(a)-1(ti)5(onshi)5(p )20(betw)5(e)-1(e)19(n)-1( the tw)5(o)19(.)]TJ
+0 -4.52 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 141.2 m
+99.366 141.2 l
+S
+BT
+12 0 0 12 200.16 137.12 Tm
+( )Tj
+ET
+243.843 141.2 m
+200.163 141.2 l
+S
+BT
+10.08 0 0 10.08 99.36 125.485 Tm
+0 Tc
+(2)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.087 Tw
+[( )-1905(I)-16(t)-16( )24(is)16( )24(im)-8(por)-8(t)-16(ant)-16( )47(t)-16(o)0( )24(m)-8(ent)-16(ion )24(a)24(t)-16( t)-16(he ou)24(t)-16(s)-8(et)-16( )24(t)-16(hat)-16( )24(t)-16(his)-8( paper)-8( c)-8(ons)-8(ider)-8(s)-8( c)-8(o)0(s)16(t)-16( bear)-8(ing pr)-8(im)-8(ar)-8(ily)-8( in)]TJ
+2.2619 -1.1905 TD
+0.111 Tw
+[(s)-8(o)0( f)-16(a)0(r)-8( as)16( it)-16( r)-8(elat)-16(es)16( t)-16(o)0( )]TJ
+10.08 0 2.143 10.08 226.56 110.476 Tm
+[(e)24(f)-16(f)-16(i)0(c)-8(ienc)-8(y)]TJ
+10.08 0 0 10.08 268.08 110.365 Tm
+[( of)8( dec)-8(is)-8(ion-)-8(m)-8(a)0(k)-8(ing.)-16( )24(T)-16(her)-8(e ar)-8(e m)-8(any)-8( )24(m)-8(o)0(r)-8(e)0( is)-8(s)-8(ues)-8( )24(t)-16(o)0( )-24(do)]TJ
+-13.9286 -1.1429 TD
+0.159 Tw
+[(wit)-16(h equit)-16(able c)-8(o)0(s)-8(t)-16( bear)-8(ing t)-16(hat)-16( ar)-8(e im)-8(por)15(t)-16(ant)-16( but)8(,)-16( alt)-16(hough )-23(t)-16(ouc)-8(hed )-23(upon,)-16( )-23(ar)-8(e )-23(not)8( )-23(t)-16(h)0(e)]TJ
+T*
+0.016 Tw
+[(f)-16(o)0(c)-8(u)0(s)-8( of)8( t)-16(his)-8( paper)-8(.)]TJ
+ET
+endstream endobj 147 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 148 0 obj << /Type /Page /Parent 152 0 R /Resources 150 0 R /Contents 149 0 R >> endobj 149 0 obj << /Length 4844 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(10)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.039 Tw
+[(S)10(e)-1(cti)5(on 3 di)5(scusses )20(pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(o)-1(n)19(-maki)5(n)19(g)-1( and c)23(o)-1(st bea)19(ri)5(ng t)21(ogethe)19(r. )-20(W)7(h)-1(e)19(n)]TJ
+0 -1.16 TD
+0.059 Tw
+[(thi)5(n)-1(ki)5(ng abo)19(ut effi)5(ci)5(en)19(t deci)5(s)3(i)5(on )20(maki)5(ng,)21( cost be)19(ari)5(ng i)5(s)3( )20(a )-20(facto)19(r)-4( )-20(that )-20(c)23(annot be)]TJ
+T*
+-0.001 Tw
+[(separate)19(d)-1( out,)21( so i)5(t)1( i)5(s)3( usef)21(ul)5( to consi)25(der t)21(hem b)19(o)-1(th at )20(once.)]TJ
+0 -2.3 TD
+0.359 Tw
+[(S)10(e)-1(cti)5(on 4 consi)5(d)-1(e)19(r)-4(s the )20(thi)5(r)-4(d )20(of ou)19(r devol)5(uti)25(on ques)23(ti)5(ons: )-20(w)5(h)-1(i)5(c)3(h )-20(l)25(e)-1(vel)5( )-20(of)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(govern)19(m)-4(ent i)5(s)3( th)19(e most)21( effi)5(ci)5(ent i)25(m)-4(pl)5(em)16(enter)16(?)]TJ
+0 -2.32 TD
+0.079 Tw
+[(In )20(some cas)23(e)-1(s i)5(t)1( i)5(s)3( di)5(ffi)5(cul)5(t)1( )20(to sepa)19(rate )20(pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(o)19(ns fro)19(m)-4( i)5(m)-4(pl)5(e)19(m)-4(entati)25(on;)]TJ
+0 -1.16 TD
+0.059 Tw
+[(devol)5(uti)5(on )20(a)19(nd )20(dec)23(entral)5(i)5(s)3(a)19(t)1(i)5(on )20(a)19(r)-4(e )20(i)5(n)-1(tri)25(n)-1(si)5(cal)5(l)5(y)3( l)5(i)5(n)-1(ked. S)10(e)-1(cti)5(o)19(n 5 di)5(scusses)23( the)]TJ
+0 -1.14 TD
+0.004 Tc
+0.178 Tw
+[(probl)6(ems)24( )20(w)6(h)0(i)6(c)4(h )20(ari)6(s)24(e )20(w)6(hen )20(t)22(here )40(are c)24(onfl)6(i)6(c)4(ts betw)6(e)20(en opti)26(m)-3(al)6( dev)24(ol)6(uti)6(on of)]TJ
+0 -1.16 TD
+0.278 Tw
+[(deci)6(s)4(i)6(on )20(maki)6(n)20(g)0( )20(and )20(c)24(o)0(st bea)20(ri)6(ng a)20(nd the)20( opti)6(m)17(al)6( l)6(e)0(vel)6( of g)20(o)0(vern)20(ment )20(for)]TJ
+T*
+[(i)6(m)-3(pl)6(ement)22(ati)6(on.)]TJ
+0 -2.32 TD
+0.002 Tc
+0.34 Tw
+[(A)9(s)2( we pr)-5(oceed w)24(e)-2( will build up )20(a diag)18(r)-5(a)-2(m)-5(,)0( t)20(hat r)15(epr)-5(es)22(ents a f)20(r)-5(am)15(ewor)-5(k)]TJ
+0 -1.14 TD
+[(summari)5(si)5(n)19(g)-1( the c)23(o)-1(mpl)5(e)-1(x i)25(n)-1(ter)16(r)-4(el)5(ati)5(ons )20(betw)5(een factors)23( )-20(that )-20(i)5(n)-1(fl)25(uence our)]TJ
+0 -1.16 TD
+0.299 Tw
+[(deci)5(s)3(i)5(ons. )20( )20(T)14(h)-1(i)5(s)3( fra)19(m)-4(ew)5(ork )20(provi)5(des)23( a usef)21(ul)5( and )20(rel)5(a)-1(ti)5(vel)5(y)3( si)5(m)16(p)-1(l)5(e)-1( w)5(a)-1(y of)]TJ
+T*
+-0.001 Tw
+[(appl)5(yi)5(ng ou)19(r the)19(o)-1(ry of )20(devol)5(uti)5(o)19(n to r)16(eal)5( R)5(M)-4(A)10( si)5(tuati)5(o)19(ns.)]TJ
+0 -2.32 TD
+0.16 Tw
+[(S)9(e)-2(ction )20(6 )20(deals )20(with)18( )20(account)20(ability and)18( sover)-5(e)-2(i)24(gnty issues.)20( Conclusions )20(and)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(recomm)16(endati)25(ons fol)5(l)5(o)-1(w)5( i)5(n)-1( s)23(e)-1(cti)5(on 7.)]TJ
+10.08 0 0 10.08 99.36 468.205 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 454.64 Tm
+0.002 Tc
+0.2 Tw
+[(A)9( com)-5(panion )20(pape)18(r)-5( \()-5(W)6(P)9( 98/7a)18(\))-5( illustr)15(a)-2(tes how t)20(he fr)15(am)-5(ewo)18(r)-5(k applies to )-20(an)]TJ
+0 -1.16 TD
+0.039 Tw
+[(actual)5( )20(R)5(M)-4(A)10( )20(pr)16(obl)5(em. )20( )40(It )20(deal)5(s w)5(i)5(t)21(h si)5(gni)5(fi)5(cant n)19(a)-1(tu)19(ral)5( ar)16(eas and)19( the p)19(r)-4(ovi)5(s)3(i)5(on o)19(f)]TJ
+T*
+0.02 Tw
+[(kiwi )20(habitat in th)18(e F)-7(a)18(r)-5( Nor)-5(t)20(h. T)13(h)-2(is dr)-5(aws )20(out issues )20(of balanc)22(ed social )20(decision-)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(maki)5(ng an)19(d effi)5(ci)5(ent)21( provi)5(s)3(i)5(o)19(n w)5(hen b)19(o)-1(th l)5(o)-1(cal)5( )20(and )-20(ce)19(ntral)5( )-20(g)19(o)-1(vern)19(ment )-20(i)5(n)19(put )-20(a)19(r)-4(e)]TJ
+0 -1.16 TD
+[(essenti)4(a)-2(l)4(.)]TJ
+10.08 0 0 10.08 99.36 384.925 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 371.36 Tm
+0.003 Tc
+0.039 Tw
+[(The pa)19(per i)5(s)3( l)5(o)19(ng. R)5(e)-1(a)19(ders may )-20(w)5(i)5(s)3(h )-20(to be )-20(sel)5(e)-1(cti)5(v)23(e )-20(i)5(n)-1( )-20(the aspects )-20(t)21(hey )-20(re)19(ad.)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(The co)20(mpani)6(on)20( pape)20(r \(W)8(P)11( 98/7)20(a)0(\), f)22(o)0(r exa)20(m)-3(pl)6(e, ca)20(n be )20(read )-20(i)6(n)20(depe)20(ndentl)6(y)4( )-20(o)20(f)]TJ
+0 -1.14 TD
+0.003 Tc
+0.139 Tw
+[(the )20(mai)5(n)-1( t)21(heor)16(eti)5(c)3(al)5( secti)5(o)19(n. W)7(e)-1( ho)19(pe that)21( the l)5(i)5(n)-1(ks )20(betw)5(een )20(the th)19(eory a)19(n)-1(d)]TJ
+0 -1.16 TD
+0.004 Tc
+0.318 Tw
+[(compani)6(on)20( )20(pape)20(r )20(ar)17(e cl)6(ear)17(, so the)20( rea)20(der w)6(ho w)26(ants m)17(o)0(re )20(detai)6(l)6( on )20(the)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(concepts use)19(d)-1( i)5(n)-1( the)19( case ca)19(n easi)5(l)5(y)3( fi)5(nd )20(the re)19(l)5(e)-1(vant t)21(heor)16(eti)5(c)3(al)5( secti)5(o)-1(n)19(.)]TJ
+ET
+endstream endobj 150 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 151 0 obj << /Type /Pages /Kids [ 123 0 R 152 0 R 176 0 R 200 0 R 224 0 R 250 0 R 278 0 R ] /Count 70 /MediaBox [ 0 0 595 842 ] >> endobj 152 0 obj << /Type /Pages /Kids [ 148 0 R 26 0 R 29 0 R 31 0 R 34 0 R 161 0 R 36 0 R 39 0 R 41 0 R 47 0 R ] /Count 10 /Parent 151 0 R >> endobj 153 0 obj << /Length 7527 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(11)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+-0.002 Tc
+0.004 Tw
+[(2)-1806(W)2(HY AND WHAT)-11( SHOUL)-10(D)0( WE REGUL)-11(A)0(T)-11(E)5(?)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.038 Tw
+[(The )20(m)17(a)0(i)6(n)0( )20(pu)20(rpose )20(o)20(f)2( thi)6(s)4( pa)20(per i)6(s)4( t)22(o)0( add)20(ress qu)20(esti)6(ons ab)20(out )]TJ
+12 0 2.551 12 432.96 719.6 Tm
+(how)Tj
+12 0 0 12 455.04 719.6 Tm
+-0.022 Tc
+0.064 Tw
+[( we)-26( r)-29(e)-26(g)-6(u)-26(l)-20(a)-26(t)-24(e)-26(.)]TJ
+-29.64 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(H)6(o)0(w)6(e)0(ver, be)20(fore w)6(e)20( begi)6(n w)26(e)0( need)20( to b)20(r)-3(i)6(e)0(fl)6(y re)20(mi)6(nd ou)20(rsel)6(ves o)20(f)2( the )20(reasons)]TJ
+0 -1.16 TD
+[(w)6(h)0(y )20(w)6(e)0( regul)26(ate at )20(al)6(l)6(,)2( and t)22(he ra)20(ti)6(onal)6(e b)20(ehi)6(nd w)6(h)20(at w)6(e)0( deci)26(de to co)20(ntrol)6(.)2( )20( A)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(ful)5(l)5(e)-1(r exposi)5(t)1(i)25(on of t)21(hese a)19(r)-4(gum)16(ents i)5(s)3( gi)5(ve)19(n i)5(n)-1( A)10(ppen)19(di)5(x Tw)5(o.)]TJ
+/F3 1 Tf
+0.96 -2.32 TD
+0.007 Tc
+-0.005 Tw
+[(\223)7(The )20(pur)16(p)18(o)-2(se )20(of t)20(h)-2(i)5(s)3( A)9(c)23(t i)5(s)3( )20(to )20(pr)16(om)16(ote )20(the s)23(u)-2(s)23(t)0(ai)5(n)18(a)3(bl)5(e m)16(a)23(nag)18(e)3(m)16(e)3(nt )20(of)]TJ
+3.64 -1.2 TD
+0.004 Tc
+-0.002 Tw
+[(natur)13(a)0(l )20(an)15(d p)15(h)-5(ysica)20(l r)13(eso)15(ur)13(ces.\224 \(S)11(ec)20(tio)15(n)-5( 5, R)26(M)-3(A)6( 1991)20(\))]TJ
+/F5 1 Tf
+-4.6 -2.32 TD
+0.003 Tc
+0.099 Tw
+[(W)7(h)-1(y i)5(s)3( speci)5(a)-1(l)5( l)5(egi)5(sl)5(ati)5(o)-1(n)19( need)19(ed for)16( the manag)19(ement)21( )-20(of )-20(nat)21(ural)5( )-20(a)19(nd )-20(physi)5(cal)]TJ
+0 -1.16 TD
+[(resourc)23(e)-1(s?)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.004 Tc
+-0.002 Tw
+[(E)11(x)0(ter)13(n)-5(alitie)20(s an)15(d)-5( P)11(u)15(b)-5(lic G)22(o)-5(o)15(d)-5(s)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.038 Tw
+[(The )20(fun)20(dame)20(n)0(tal)6( p)20(r)-3(obl)6(em)17( w)6(i)6(t)2(h reso)20(urces i)6(s)4( t)22(hat m)17(any of t)22(he p)20(r)-3(ope)20(rty ri)6(ghts)24( are)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(not ful)5(l)5(y)3( al)5(l)5(o)-1(cat)21(ed and)19( enfo)19(r)-4(ced. )-20(P)10(r)-4(o)19(perty ri)5(ghts need )-20(t)21(o)-1( )-20(be )-20(d)19(e)-1(fi)5(ned, transf)21(e)-1(rabl)5(e)]TJ
+0 -1.14 TD
+0.059 Tw
+[(and )20(enfo)19(r)-4(ceabl)25(e )20(for )40(effi)5(ci)5(ent )40(markets)23( to func)23(ti)5(on. W)7(h)-1(e)19(never )20(prop)19(erty )20(ri)5(ghts a)19(r)-4(e)]TJ
+0 -1.16 TD
+0.099 Tw
+[(i)5(n)-1(compl)5(e)-1(tel)5(y)3( )40(defi)5(ned )40(or )20(e)19(n)-1(force)19(d)-1(, )20(exte)19(rnal)5(i)5(t)1(i)5(e)-1(s )20(a)19(nd pu)19(bl)5(i)5(c)3( good si)5(t)21(uati)5(ons a)19(r)-4(i)5(s)3(e)]TJ
+T*
+0.159 Tw
+[(and reso)19(urces c)23(an be )20(al)5(l)5(o)-1(cated i)25(neffi)5(ci)5(entl)5(y)3( w)5(i)5(t)1(h)19(out )-20(i)5(n)-1(te)19(rventi)5(o)-1(n)19(.)1( )-20( )-20(In addi)5(ti)5(on,)]TJ
+T*
+0 Tc
+0.082 Tw
+[(so)-4(m)-7(e)-4( a)-4(g)-4(e)16(n)-4(t)-2(s will b)-4(e)-4( a)16(b)-4(le)-4( to)-4( cla)-4(i)22(m)-7( th)-4(e)-4( u)16(n)-4(a)-4(llo)-4(ca)-4(te)16(d)-4( r)-7(e)-4(so)16(u)-4(r)-7(ce)-4(s f)18(o)-4(r)-7( th)16(e)-4(i)2(r)-7( )-20(o)-4(w)2(n)-4( u)-4(s)0(e)-4(.)]TJ
+T*
+0.003 Tc
+0.339 Tw
+[(Thi)5(s)3( i)5(s)3( an u)19(ndem)16(ocrati)5(c, i)5(n)19(equi)5(tabl)25(e )-20(w)5(a)-1(y )-20(to al)5(l)5(o)-1(cate resourc)23(e)-1(s )-20(that)21( )-20(w)5(e)-1(re)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(previ)5(ousl)5(y)3( h)19(e)-1(l)5(d)-1( i)5(n)-1( com)16(m)-4(on.)]TJ
+0 -2.32 TD
+0.419 Tw
+[(In many i)5(n)-1(st)21(ances p)19(r)-4(i)5(v)3(ate s)23(o)-1(l)5(u)-1(ti)5(ons a)19(r)-4(e possi)25(bl)5(e. T)14(he C)5(oase)19( The)19(o)-1(re)19(m)]TJ
+0 -1.16 TD
+0.119 Tw
+[(suggests )20(th)19(at, )20(w)5(h)-1(e)19(r)-4(e )20(tra)19(n)-1(sacti)5(on )20(c)23(o)-1(sts )20(ar)16(e l)5(o)-1(w)5(,)1( al)5(l)5( th)19(at i)5(s)3( necess)23(a)-1(ry i)5(s)3( fo)19(r the)]TJ
+T*
+0.004 Tc
+0.138 Tw
+[(S)11(t)2(ate to defi)6(n)20(e and )20(enfor)17(ce pr)17(operty)24( ri)6(ghts,)22( )-20(and )-20(n)20(egoti)6(a)0(ti)6(o)20(n)0( )-20(and the )-20(co)20(mmon)]TJ
+0 -1.14 TD
+0.001 Tc
+0.061 Tw
+[(law )20(system)-6( will allocate )20(r)-6(e)-3(sou)17(r)-6(ces effici)23(ently. T)12(h)-3(is is a ve)17(r)-6(y)1( unint)19(r)-6(u)-3(sive fo)17(r)-6(m)-6( o)17(f)]TJ
+0 -1.16 TD
+0.004 Tc
+[(regul)6(ati)6(o)0(n)20(.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.119 Tw
+[(R)5(egul)5(ati)5(on of)21( non)19(-publ)5(i)5(c)3( ext)21(e)-1(rnal)5(i)5(t)1(i)5(e)-1(s )20(\(e.g.)21(:)1( obstr)16(ucti)5(on o)19(f)1( )-20(pri)5(v)3(at)21(e )-20(vi)5(ew)5(s\) )-20(co)19(ul)5(d)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.023 Tw
+[(b)-5(e)-5( lim)-8(ite)-5(d)-5( to)15( d)-5(e)-5(f)-3(in)-5(in)15(g)-5( p)-5(r)-8(o)15(p)-5(e)-5(r)-8(ty r)-8(i)1(g)-5(h)-5(t)-3(s )-20(a)15(n)-5(d)-5( )-20(fa)-5(cilita)-5(t)-3(io)15(n)-5( )-20(\226)-5( )-20(a)-5(l)1(so)15( )-20(r)-8(e)-5(la)-5(tive)-5(ly u)-5(n)-5(i)1(n)-5(t)-3(r)12(u)-5(sive)-5(.)]TJ
+0 -1.14 TD
+0.002 Tc
+0.12 Tw
+[(Local )20(gove)18(r)-5(nm)-5(e)18(n)-2(t )20(should)18( )20(be a)18(b)-2(le to facilita)18(t)0(e ag)18(r)-5(eem)15(ents on)18( exter)15(nalities that)]TJ
+0 -1.16 TD
+0.004 Tc
+0.078 Tw
+[(affect very s)24(m)-3(al)6(l)6( nu)20(mbers)24( of pe)20(opl)6(e. )20(Thei)6(r rol)6(e)0( )-20(sh)20(oul)6(d )-20(be )-20(l)6(i)26(mi)6(ted )-20(to)20( )-20(medi)6(a)20(t)2(i)6(on,)]TJ
+T*
+0.158 Tw
+[(and reco)20(rdi)6(ng )20(and e)20(n)0(forci)6(n)20(g agr)17(eeme)20(n)0(ts am)17(ong aff)22(e)0(cted )20(parti)6(es.)22( )-20(E)11(l)6(sew)6(here)]TJ
+T*
+0.002 Tc
+0.02 Tw
+[(they can r)15(educe )20(tr)-5(ansac)22(tion costs )20(by cer)-5(t)0(ifyi)24(ng the c)22(r)-5(edibility o)18(f)0( infor)15(m)-5(ation,)20( )-20(and)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(provi)6(d)0(i)6(ng a)20( foru)20(m fo)20(r di)6(scussi)6(on.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.339 Tw
+[(There)19( )20(are, )40(how)5(eve)19(r)-4(, l)5(i)5(m)-4(i)5(t)1(s to )20(pri)5(v)3(ate)19( sol)5(u)-1(ti)5(ons t)21(hat cal)5(l)5( f)21(o)-1(r m)16(o)-1(re i)5(n)-1(v)23(a)-1(si)5(ve)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(regul)6(ati)6(o)0(n)20( )20(by )20(gov)24(ernm)17(ent. )20( )40(For )20(w)6(h)0(i)6(c)24(h )20(i)6(ssues ar)17(e th)20(e fai)6(l)6(u)0(res)24( of p)20(r)-3(i)6(v)4(ate sol)6(u)0(ti)26(ons)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(to extern)19(al)5(i)5(t)1(i)5(e)-1(s suffi)5(ci)5(en)19(tl)5(y gre)19(a)-1(t that )20(furth)19(e)-1(r gov)23(ern)19(m)-4(ent regul)5(ati)25(on )-20(i)5(s)3( )-20(nee)19(ded?)]TJ
+T*
+0.019 Tw
+[(Theory)23( suggests)23( gove)19(r)-4(nme)19(n)-1(t shoul)5(d)19( focus o)19(n)-1( reg)19(u)-1(l)5(a)-1(ti)5(ng )-20(ex)23(tern)19(al)5(i)5(t)1(i)5(e)-1(s )-20(that affect)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(publ)6(i)6(c)4( )20(goods )40(and co)20(mmo)20(n pro)20(perty )20(resou)20(r)-3(ces, pa)20(rti)6(c)4(ul)6(a)20(r)-3(l)6(y)4( those t)22(hat hav)24(e the)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(fol)5(l)5(o)-1(w)5(i)5(ng char)16(acteri)5(sti)5(cs:)]TJ
+0 -2.32 TD
+(1. )Tj
+1.12 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.24 0.02 TD
+0.003 Tc
+0.219 Tw
+[(Transac)23(ti)5(on costs )20(are hi)25(gh due)19( to i)5(n)-1(fo)19(rmati)25(on asym)16(metri)25(e)-1(s or co)19(sts )-20(of)]TJ
+0 -1.16 TD
+0.159 Tw
+[(coordi)5(nati)5(o)19(n. )20( )20(T)14(h)-1(i)5(s)3( i)5(s)3( ofte)19(n the cas)23(e)-1( w)5(hen )20(an exte)19(rnal)5(i)5(t)1(y af)21(fects a l)5(a)19(rge)]TJ
+0 -1.14 TD
+0.239 Tw
+[(numbe)19(r )20(of pe)19(opl)5(e, co)19(mes f)21(r)-4(om sev)23(e)-1(ral)5( so)19(urces, )20(or has)23( effects )20(over a)]TJ
+ET
+endstream endobj 154 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 155 0 obj << /Length 7844 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(12)Tj
+-31.96 58.98 TD
+0.138 Tw
+[(numbe)20(r of yea)20(r)-3(s. A)11(i)6(r p)20(o)0(l)6(l)6(u)0(ti)6(on i)6(s)4( a )20(good )20(exampl)6(e.)22( In thi)6(s)4( si)6(t)22(uati)6(on i)6(t)2( i)6(s)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(unreaso)19(nabl)5(e t)21(o)-1( expect )20(al)5(l)5( the af)21(fected )20(parti)5(es )20(to ne)19(goti)5(a)-1(te s)23(u)-1(ccessful)5(l)5(y)3(.)]TJ
+-2.36 -2.32 TD
+(2. )Tj
+1.12 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.24 0.02 TD
+0.003 Tc
+0.039 Tw
+[(P)10(r)-4(operty )40(ri)5(ghts )20(can)19( )20(not b)19(e)-1( al)5(l)5(o)-1(cate)19(d or )20(enforce)19(d ad)19(equat)21(el)5(y. S)10(o)-1(me g)19(oods)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(are i)6(nhe)20(rentl)6(y)4( di)6(f)22(f)2(i)6(c)4(ul)6(t to al)6(l)6(o)0(c)24(a)0(te \()17(e)0(.g. fi)6(sh )20(that mi)26(grate)20(\))-3(. )-20( )-20(S)11(o)0(m)17(e)0( )-20(pro)20(perty)]TJ
+0 -1.16 TD
+0.001 Tc
+0.081 Tw
+[(r)-6(i)3(ghts ar)14(e difficult t)19(o)-3( enfo)17(r)-6(ce \()14(e)-3(.g.; lim)-6(it)19(ed liability co)17(m)-6(panies,)19( )-20(dealing )-20(wit)19(h)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(risks of pollutio)19(n)-1( rat)21(her t)21(han act)21(ual )-20(pollutio)19(n)-1(, )-20(may not )-20(tak)23(e)-1( )-20(ade)19(quate)]TJ
+T*
+0.004 Tc
+[(precauti)6(o)20(ns\).)]TJ
+-2.36 -2.3 TD
+0.003 Tc
+(3. )Tj
+1.12 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.24 0.02 TD
+0.004 Tc
+0.138 Tw
+[(S)11(o)0(me i)6(n)0(tere)20(sts are)20( not )20(repr)17(esented)20(. )-20(Thi)6(s)4( occurs )-20(w)6(i)6(t)2(h)20( )-20(hi)6(gh )-20(co)20(ordi)6(na)20(ti)6(on)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(costs )20(and )20(l)5(a)19(rge )20(i)5(m)16(bal)5(ances )20(i)25(n)-1( reso)19(urces f)21(o)-1(r ne)19(goti)5(a)-1(ti)5(on)19( \(i)5(t i)5(s)3( l)5(i)5(k)3(el)5(y to )20(affect)]TJ
+T*
+0.119 Tw
+[(envi)5(r)-4(onm)16(ental)5( g)19(r)-4(oups,)21( Mao)19(r)-4(i)5(,)1( com)16(m)-4(uni)5(ty )-20(g)19(r)-4(oups etc )-20(w)5(ho are )-20(n)19(egoti)5(a)-1(ti)5(n)19(g)]TJ
+T*
+0.004 Tc
+[(w)6(i)6(t)2(h busi)6(ness\).)22( Fu)20(rther)17(mor)17(e)0(, futu)20(re g)20(enera)20(t)2(i)6(ons )-20(a)20(r)-3(e )-20(una)20(bl)6(e )-20(to repr)17(esent)]TJ
+T*
+-0.002 Tw
+[(themsel)6(v)4(es )20(and gov)24(ern)20(m)-3(ent )20(may nee)20(d to act)22( as thei)26(r age)20(nt.)]TJ
+/F3 1 Tf
+-2.36 -2.58 TD
+0.007 Tc
+-0.025 Tw
+[(Infor)16(m)16(a)3(ti)25(on failur)16(e)3(s)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.198 Tw
+[(Imperf)22(e)0(ct i)6(n)0(fo)20(rmati)6(on)20( abou)20(t the e)20(ffects of )20(resou)20(r)-3(ce )-20(us)24(e )-20(i)6(s)4( )-20(anot)22(her )-20(i)6(m)17(port)22(ant)]TJ
+0 -1.16 TD
+0.003 Tc
+0.179 Tw
+[(market )20(f)21(a)-1(i)5(l)5(u)-1(re )20(i)5(n)19( )20(the )20(al)5(l)5(o)-1(c)23(a)-1(ti)5(on )20(of )40(resou)19(r)-4(ces; i)5(t)1( m)16(a)-1(y al)5(so w)25(a)-1(rra)19(nt gove)19(r)-4(nm)16(ent)]TJ
+T*
+[(i)5(n)-1(terventi)5(o)19(n.)]TJ
+0 -2.3 TD
+0.479 Tw
+[(Issues may b)19(e)-1( new)5( w)5(h)-1(i)5(c)3(h)19( mea)19(n)-1(s that i)5(n)19(di)5(vi)5(dual)5(s )-20(ha)19(ve )-20(not devel)5(op)19(ed)]TJ
+0 -1.16 TD
+0.004 Tc
+0.178 Tw
+[(experi)6(ence)20(,)2( and i)26(n)0(sti)6(t)2(uti)6(ons t)22(o)0( di)6(ssemi)26(nate i)6(n)0(fo)20(rma)20(ti)6(on a)20(r)-3(e poo)20(rl)6(y )-20(devel)26(oped.)]TJ
+T*
+0.003 Tc
+0.319 Tw
+[(E)10(ffects )20(may )20(be )40(unobse)19(r)-4(vabl)5(e,)21( unce)19(r)-4(tai)5(n)-1( o)19(r)-4( occur)16( over )20(a l)5(ong ti)25(me f)21(r)-4(ame.)]TJ
+T*
+0.439 Tw
+[(U)5(nderstan)19(di)5(ng th)19(e effects may )-20(r)16(equi)5(r)16(e)-1( )-20(speci)5(a)-1(l)5(i)5(s)3(ed exper)16(ti)5(se )-20(or )-20(sci)25(enti)5(f)1(i)5(c)]TJ
+T*
+0.004 Tc
+[(know)6(l)6(edge.)]TJ
+0 -2.3 TD
+0.258 Tw
+[(There)20( i)6(s)4( a rol)26(e)0( for )20(gover)17(nment)22( regul)26(ati)6(on i)6(n)0( )20(areas w)26(here t)22(here)20( are )-20(c)24(r)-3(i)6(t)2(i)6(c)4(al)]TJ
+0 -1.16 TD
+0.138 Tw
+[(i)6(n)0(formati)26(on pr)17(obl)6(ems. )20( Thes)24(e coul)6(d )20(be si)6(tuati)26(ons )-20(w)6(h)0(e)20(r)-3(e )-20(the potenti)26(a)0(l)6( )-20(har)17(m )-20(i)6(s)]TJ
+T*
+-0.002 Tw
+[(great, cos)24(t)2(s of av)24(oi)6(dance )20(are l)6(o)0(w)6( )20(rel)6(a)0(ti)6(ve t)22(o)0( the harm)17(,)2( )-20(and )-20(i)6(n)20(di)6(vi)6(dual)6( )-20(i)6(n)0(f)22(o)0(rma)20(ti)6(on)]TJ
+T*
+[(i)6(s)4( poor.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.099 Tw
+[(It )20(i)5(s)3( reason)19(abl)5(y unc)23(ontenti)5(o)19(us )]TJ
+12 0 2.551 12 266.16 300.56 Tm
+0.004 Tc
+(that)Tj
+12 0 0 12 286.32 300.56 Tm
+0.098 Tw
+[( )20(ther)17(e i)6(s)4( a rol)26(e)0( for)17( gover)17(nmen)20(t reg)20(u)0(l)6(a)0(ti)6(on i)6(n)]TJ
+-15.58 -1.26 TD
+0.003 Tc
+0.019 Tw
+[(some cases )20(of publ)5(i)5(c)3( )20(goods, )20(extern)19(al)5(i)5(t)1(i)5(e)-1(s and i)25(n)-1(for)16(m)-4(ati)5(on f)21(a)-1(i)5(l)5(u)-1(res.)]TJ
+10.08 0 0 10.08 451.44 288.445 Tm
+0 Tc
+0 Tw
+(3)Tj
+12 0 0 12 456.96 285.44 Tm
+0.004 Tc
+0.018 Tw
+[( Let\222)6(s)4( )-20(r)17(e)0(turn)]TJ
+-29.8 -1.16 TD
+0.118 Tw
+[(to our ce)20(ntral)6( c)24(oncer)17(n. Gi)6(ven t)22(hat w)6(e)0( )20(are g)20(o)0(i)6(ng to )20(regul)6(a)20(t)2(e som)17(e)0( goo)20(ds and)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(acti)5(vi)5(ti)5(es, w)5(hat l)5(e)-1(vel)5( )20(of gove)19(r)-4(nm)16(ent i)5(s)3( best)21( pl)5(aced t)21(o)-1( do i)5(t)21(?)]TJ
+0 -4.28 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 210.56 m
+99.366 210.56 l
+S
+BT
+12 0 0 12 200.16 206.48 Tm
+( )Tj
+ET
+243.843 210.56 m
+200.163 210.56 l
+S
+BT
+10.08 0 0 10.08 99.36 194.845 Tm
+0 Tc
+(3)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.063 Tw
+[( )-1929(M)-8(u)0(c)-8(h)0( debat)-16(e r)-8(ages)-8( as)-8( )23(t)-16(o)0( t)-16(he na)24(t)-16(u)0(r)-8(e)0( and s)-8(c)-8(ope of)8( t)-16(hat)8( )-24(r)-8(ole.)-16( )-24( A)-8(l)0(m)-8(o)0(s)-8(t)-11( )-24(ev)-8(er)15(y)-8(t)-16(hing )-24(pr)-8(oduc)-8(es)]TJ
+2.2619 -1.1905 TD
+0.254 Tw
+[(ex)-8(t)-16(e)0(r)-8(nalit)-16(ies)-8( \226 s)-8(m)-8(iling,)-16( dr)-8(es)-8(s)-8( s)-8(ens)-8(e,)8( old c)-8(a)0(r)-8(s)-8( on)24( f)-16(r)-8(ont)8( )-24(lawns)-8(,)-16( )-24(aes)-8(t)-16(het)-16(ic)-8(s)16( )-24(of)8( )-24(buildings)-8(.)]TJ
+0 -1.1429 TD
+0.182 Tw
+[(W)-17(hic)-8(h ex)-8(t)-16(e)0(r)-8(nalit)-16(ies)-8( and public)-8( goods)-8( s)-8(hould )-24(t)-16(he )-24(gov)-8(er)-8(nm)-8(ent)-16( )-24(c)-8(a)0(r)-8(e)0( )-24(about)-16(? )-24(How )-24(m)-8(u)0(c)-8(h)]TJ
+T*
+0.325 Tw
+[(r)-8(egulat)-16(ion s)-8(hould t)-16(her)-8(e be? W)-17(her)-8(e is)-8( )24(t)-16(he lim)-8(it)-16( of)8( gov)-8(er)-8(nm)-8(ent)-16( inv)-8(olv)-8(em)-8(ent)-16(? )24( I)-16(t)8( )-24(is)]TJ
+T*
+0.016 Tw
+[(im)-8(por)-8(t)-16(ant)-16( t)-16(o)0( )24(k)-8(eep in m)-8(ind t)-16(hat)8( t)-16(his)-8( is)16( ult)-16(im)-8(at)-16(ely)-8( a polit)-16(ic)-8(al ques)-8(t)-16(ion and t)-16(he m)-8(o)0(s)-8(t)-16( )-24(bas)-8(ic)16( )-24(one)]TJ
+T*
+0.135 Tw
+[(t)-16(hat)-16( m)-8(u)0(s)16(t)-16( be dec)-8(ided by)-8( what)-16(ev)-8(er)15( lev)-8(el of)-16( gov)-8(er)-8(nm)-8(ent)-16( )-24(m)15(a)0(k)-8(e)0(s)-8( )-24(dec)-8(is)-8(ions)-8(.)-16( )-24(P)-8(eople )-24(hav)-8(e)]TJ
+T*
+0.063 Tw
+[(s)-8(t)-16(r)-8(ong )23(and div)-8(er)-8(s)-8(e)0( s)-8(ubjec)-8(t)-16(i)0(v)-8(e)0( pr)-8(ef)-16(er)-8(enc)-8(es)-8( about)8( t)-16(his)-8(.)8( W)-17(hile logic)-8( and analy)-8(s)-8(i)0(s)-8( c)-8(an c)-8(lar)-8(if)-16(y)]TJ
+0 -1.1667 TD
+0.421 Tw
+[(t)-16(he is)-8(s)-8(ues)-8( and em)-8(pir)-8(ic)-8(al ev)-8(idenc)-8(e c)-8(an inf)-16(or)-8(m)-8( )24(t)-16(hem)-8(,)-16( ques)16(t)-16(ions)-8( about)-16( t)-16(he r)-8(ole o)24(f)]TJ
+0 -1.1429 TD
+0.254 Tw
+[(gov)-8(er)-8(nm)-8(ent)-16( )24(ar)-8(e,)-16( )24(ult)-16(im)-8(at)-16(ely)16(,)-16( )24(a )24(m)-8(a)0(t)-16(t)-16(e)0(r)15( of)-16( pr)-8(e)24(f)-16(er)-8(enc)-8(es)-8( and judgem)-8(ent)-16(,)-16( not)8( an objec)-8(t)-16(i)0(v)-8(e)]TJ
+T*
+[(is)-8(s)-8(ue.)]TJ
+ET
+endstream endobj 156 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 157 0 obj << /Length 8053 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(13)Tj
+/F3 1 Tf
+-34.32 58.86 TD
+-0.001 Tc
+0.003 Tw
+[(3)-1805(P)6(OL)-10(IT)-10(ICAL)-10(/SOCIAL)-10( DECISION M)-8(AKING AND COST)-10( BEARING)]TJ
+10.08 0 0 10.08 477.6 747.603 Tm
+0 Tc
+0 Tw
+(4)Tj
+/F5 1 Tf
+12 0 0 12 99.36 718.64 Tm
+0.004 Tc
+0.618 Tw
+[(W)8(hen )20(the )20(A)11(m)-3(e)20(r)-3(i)6(c)4(an )20(set)22(t)2(l)6(e)0(rs )20(r)17(o)0(se ag)20(ai)6(nst the)20( B)11(r)-3(i)6(t)2(i)6(s)4(h i)6(n)0( the)20( W)8(a)0(r of)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(Indepen)19(dence, )20(t)21(hei)5(r ca)19(tch cry w)5(a)-1(s)23( \223no )20(taxati)5(on w)5(i)5(t)21(hout )20(repres)23(entati)5(o)19(n\224. O)21(n)-1(e)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(argum)17(ent fo)20(r devol)6(u)20(t)2(i)6(on of )20(resou)20(r)-3(ce m)17(anagem)17(ent i)6(s)4( )20(based o)20(n)0( a si)6(mi)6(l)6(a)20(r )-20(conce)20(r)-3(n:)]TJ
+T*
+0.003 Tc
+0.319 Tw
+[(concern )20(t)21(hat )20(th)19(ose )20(w)5(ho a)19(r)-4(e af)21(fected, )20(both p)19(o)-1(si)5(ti)5(vel)5(y)3( and)19( negati)5(v)23(el)5(y, by a)]TJ
+0 -1.14 TD
+0.099 Tw
+[(regul)5(ati)5(o)-1(n)19( are )20(those w)5(h)19(o are)19( abl)5(e )-20(to)19( )-20(contr)16(o)-1(l)5( )-20(that regul)5(a)19(t)1(i)5(on. )-20( )-20(If an )-20(acti)5(vi)5(ty has)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(onl)5(y l)5(o)-1(cal)5( effects)23(,)1( the)19(r)-4(e i)5(s)3( no c)23(a)-1(l)5(l)5( for al)5(l)5(o)-1(w)5(i)5(n)19(g the )20(prefe)19(r)-4(ences)23( of di)5(sta)19(n)-1(t acto)19(rs )-20(to)]TJ
+T*
+[(have any pl)25(ay or f)21(o)-1(r fo)19(rci)5(ng th)19(em to)19( bea)19(r any of)21( the costs)23(.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.005 Tc
+-0.003 Tw
+[(The P)12(r)14(obl)23(em)14( with P)32(ublic)21( Go)16(ods)21(: P)12(r)14(efer)14(ence R)7(e)21(vela)21(t)-2(io)16(n)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+-0.001 Tw
+[(The fun)19(dame)19(n)-1(tal)5( p)19(r)-4(obl)5(em)16( w)5(i)5(t)1(h effi)5(ci)5(ent)21( publ)5(i)5(c)3( go)19(od )-20(p)19(r)-4(ovi)5(s)3(i)5(on )-20(i)5(s)3( )-20(th)19(at )-20(gove)19(r)-4(nm)16(ent)]TJ
+0 -1.14 TD
+0.004 Tc
+0.158 Tw
+[(i)6(s)4( unabl)6(e to )20(reveal)6( )20(pri)6(v)4(ate)20( pref)22(erenc)24(es for )20(publ)6(i)6(c)4( go)20(ods. )20(The val)6(u)20(e of m)17(any)]TJ
+0 -1.16 TD
+0.003 Tc
+0.519 Tw
+[(consumpti)5(o)19(n goo)19(ds, both)19( publ)5(i)5(c)3( an)19(d pri)5(v)3(a)19(t)1(e, i)5(s)3( l)5(a)-1(r)16(gel)5(y subj)5(ecti)5(v)23(e)-1(, )-20(and)]TJ
+T*
+0.219 Tw
+[(depende)19(nt on i)5(n)19(di)5(vi)5(dual)5( p)19(r)-4(efe)19(r)-4(ences rathe)19(r)-4( )-20(than)19( )-20(havi)5(ng obj)5(ecti)5(ve )-20(p)19(r)-4(oduc)23(ti)5(ve)]TJ
+T*
+0.119 Tw
+[(val)5(ue. H)5(o)-1(w)5(e)-1(ve)19(r, i)5(n)-1( th)19(e case of)21( pri)5(v)3(at)21(e goods)23(, )-20(consu)19(m)-4(ers reveal)5( )-20(t)21(hei)5(r )-20(p)19(r)-4(i)5(v)3(ate)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(prefer)17(ences a)20(nd ma)20(rgi)6(nal)6( v)24(a)0(l)6(uati)6(ons t)22(h)0(rou)20(gh thei)26(r pu)20(rchases. )-20( The )-20(l)26(e)0(vel)6( )-20(and)]TJ
+0 -1.14 TD
+0.003 Tc
+0.119 Tw
+[(al)5(l)5(o)-1(cati)5(on )20(of )40(pri)5(v)3(ate )20(goods i)5(s)3( )20(paret)21(o effi)5(ci)5(ent)21( i)5(n)-1( a w)5(e)-1(l)5(l)5( fu)19(ncti)5(oni)5(ng )20(mark)23(et. N)5(o)]TJ
+0 -1.16 TD
+0.159 Tw
+[(equi)5(val)5(ent )20(market)21( mech)19(ani)5(sm exi)5(s)3(ts )20(to pr)16(ovi)5(de pu)19(bl)5(i)5(c)3( goods,)21( w)5(h)-1(i)5(c)3(h )-20(mak)23(e)-1(s )-20(i)5(t)]TJ
+T*
+0.219 Tw
+[(di)5(ffi)5(cul)5(t)1( )20(to )20(deci)5(d)19(e )20(the )20(effi)5(ci)5(ent l)5(e)-1(v)23(e)-1(l)5( of pu)19(bl)5(i)5(c)3( goods.)21( In ad)19(di)5(ti)5(on, n)19(o)-1( ma)19(rket)]TJ
+T*
+-0.001 Tw
+[(forces p)19(r)-4(ovi)5(de i)5(n)-1(ce)19(nti)5(v)3(es fo)19(r effi)5(ci)5(ent)21( pro)19(ducti)5(on.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.058 Tw
+[(A)11(t)2( the opti)6(m)-3(al)6( l)26(e)0(vel)6( of p)20(ubl)6(i)6(c)4( goo)20(d provi)6(s)4(i)6(o)20(n, the s)24(u)0(m of)22( al)6(l)6( ma)20(rgi)6(nal)6( )-20(val)6(u)20(ati)6(ons)]TJ
+0 -1.16 TD
+0.118 Tw
+[(i)6(s)4( equal)6( to t)22(he ma)20(rgi)6(nal)6( c)24(o)0(st \(S)11(amu)20(e)0(l)6(s)4(on, 1)20(955\).)22( If )-20(i)6(ndi)6(vi)6(d)20(ual)6(s\222)6( )-20(shar)17(es )-20(of )-20(th)20(e)]TJ
+T*
+0.003 Tc
+0.219 Tw
+[(costs of pr)16(ovi)5(d)-1(i)5(ng a )20(publ)5(i)5(c)3( go)19(od ar)16(e rel)5(a)19(ted )-20(to )-20(t)21(hei)5(r )-20(st)21(ated )-20(val)25(uati)5(ons, )-20(t)21(hen)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(i)6(ndi)6(vi)6(dual)6(s have )20(an i)6(n)0(cen)20(t)2(i)6(v)4(e to u)20(nders)24(t)2(ate the)20(i)6(r m)17(a)0(rgi)6(nal)6( v)24(a)0(l)6(uati)6(on.)22( Thi)6(s)4( occurs)]TJ
+T*
+-0.001 Tc
+0.063 Tw
+[(b)-5(e)-5(c)-1(a)-5(u)-5(s)-1(e)-5( a)-5( )20(d)-5(e)-5(c)-1(r)-8(e)15(a)-5(s)-1(e)-5( in)-5( a)15(n)-5( in)-5(d)-5(i)1(vid)-5(u)-5(a)-5(l\222s st)17(a)-5(t)-3(e)-5(d)-5( va)-5(l)21(u)-5(a)-5(t)-3(io)-5(n)-5( will h)-5(a)-5(v)19(e)-5( a)-5( sm)12(a)-5(ll )-20(im)-8(p)-5(a)-5(c)-1(t)]TJ
+0 -1.14 TD
+0.123 Tw
+[(o)-5(n)-5( th)-5(e)-5( le)-5(ve)-5(l )20(o)-5(f)-3( p)-5(r)12(o)-5(v)-1(isio)-5(n)-5(.)-3( Sh)-5(e)-5( will, h)15(o)-5(we)-5(ve)-5(r)-8(,)-3( )20(p)-5(a)-5(y)-1( a)-5( lo)-5(we)15(r)-8( sh)-5(a)15(r)-8(e)-5( o)-5(f)-3( c)19(o)-5(st fo)-5(r)12( a)-5(l)1(l)]TJ
+0 -1.16 TD
+0.002 Tc
+0.02 Tw
+[(units of the)18( good.)20( P)9(eople will choos)22(e to )-20(u)18(nder)-5(st)20(ate )-20(th)18(eir)-5( )-20(valua)18(t)0(ion )-20(an)18(d )-20(fr)-5(e)18(e)-2( )-20(r)-5(i)4(de)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(on )20(othe)20(r\222)6(s )20(contri)26(buti)6(ons )40(\(B)11(ergst)22(r)-3(om, B)11(l)6(um)17(e and V)11(a)20(ri)6(an, 1)20(986\).)22( In con)20(t)2(rast, i)6(f)]TJ
+T*
+0.003 Tc
+0.119 Tw
+[(cost )20(shares )40(are )20(not l)5(i)5(n)-1(ked)19( to pe)19(opl)5(e\222)5(s res)23(ponses, i)5(t)21( costs a p)19(e)-1(rson)19( nothi)5(n)19(g)-1( to)]TJ
+0 -9.02 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 210.56 m
+99.366 210.56 l
+S
+BT
+12 0 0 12 200.16 206.48 Tm
+( )Tj
+ET
+243.843 210.56 m
+200.163 210.56 l
+S
+BT
+10.08 0 0 10.08 99.36 194.845 Tm
+0 Tc
+(4)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.016 Tw
+[( )-1976(T)-16(he ar)-8(gum)-8(ent)-16(s)-8( out)-16(lined in t)-16(his)-8( )24(s)-8(e)0(c)-8(t)-16(ion all deal wit)-16(h is)-8(s)-8(ues)-8( of)8( ef)-16(f)-16(i)0(c)-8(ienc)-8(y)-8(.)8( )24(I)-16(f)8( pr)-8(ef)-16(er)-8(enc)-8(es)-8( ar)-8(e)]TJ
+2.2619 -1.1905 TD
+0.206 Tw
+[(not)-16( well r)-8(epr)-8(es)-8(ent)-16(ed and/)-16(or)-8( dec)-8(is)-8(ions)-8( ar)-8(e unbalanc)-8(ed,)-16( t)-16(her)-8(e m)-8(a)0(y)-8( be oppor)-8(t)-16(unit)-16(ies)-8( )24(f)-16(o)0(r)]TJ
+0 -1.1429 TD
+0.159 Tw
+[(par)-8(et)-16(o )24(im)-8(pr)-8(ov)-8(em)-8(ent)-16(.)-16( )48( )24(Cos)-8(t)8( )24(bear)-8(ing )24(als)-8(o has)-8( et)-16(hic)-8(al im)-8(plic)-8(at)-16(ions)-8( alt)-16(hough dis)-8(c)-8(u)0(s)-8(s)-8(ion of)]TJ
+T*
+0.301 Tw
+[(dis)-8(t)-16(r)-8(ibut)-16(ional is)-8(s)-8(ues)-8( is)-8( out)-16(s)-8(ide t)-16(he s)-8(c)-8(ope of)8( t)-16(his)-8( paper)-8(.)8( O)8(ne point)-16( t)-16(o)24( )-24(not)-16(e )-24(f)-16(o)0(r)15( )-24(our)]TJ
+T*
+0.421 Tw
+[(pur)-8(pos)-8(es)-8(,)-16( howev)-8(er)-8(,)-16( is)-8( )24(t)-16(hat)-16( nat)-16(ional gov)-8(er)-8(nm)-8(ent)-16( is)16( bet)-16(t)-16(e)0(r)-8( a)24(t)-16( r)-8(edis)-8(t)-16(r)-8(ibut)-16(ion.)-16( )24( )-23(Loc)-8(al)]TJ
+T*
+0.04 Tw
+[(gov)-8(er)-8(nm)-8(ent)-16(s)-8( )24(c)-8(annot)-16( r)-8(edis)-8(t)-16(r)-8(ibut)-16(e inc)-8(om)-8(e)24( bet)-16(ween or)-8( ev)-8(en wit)-16(hin t)-16(he jur)-8(is)-8(dic)-8(t)-16(ion.)-16( )24( Nat)-16(ional)]TJ
+T*
+0.063 Tw
+[(gov)-8(er)-8(nm)-8(ent)-16( c)-8(ould im)-8(pos)-8(e high c)-8(o)0(s)-8(t)-16(s)-8( on one jur)-8(is)-8(dic)-8(t)-16(ion or)-8( gr)-8(oup \()-8(a)24( m)-8(inor)-8(it)-16(y)-8( o)24(f)-16( any)-8( )23(t)-16(y)-8(pe\))]TJ
+0 -1.1667 TD
+0.016 Tw
+[(par)-8(t)-16(i)0(c)-8(ular)-8(ly)-8( if)-16( dec)-8(is)-8(ion m)-8(a)0(k)-8(ing is)-8( unbalanc)-8(ed.)-16( Dis)-8(c)-8(u)0(s)-8(s)-8(ion of)-16( )24(t)-16(his)-8( c)-8(an be )24(f)-16(ound in )-24(A)-8(ppendix)]TJ
+0 -1.1429 TD
+0 Tc
+[(F)-8(i)8(ve)8(.)]TJ
+ET
+endstream endobj 158 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 159 0 obj << /Length 8111 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(14)Tj
+-34.32 58.98 TD
+0.038 Tw
+[(overstate )20(thei)6(r v)24(a)0(l)6(uati)6(ons i)26(n)0( an at)22(tempt)22( to gai)6(n )20(mor)17(e)0( of th)20(e )-20(publ)6(i)6(c)4( good. )-20( Thes)24(e)]TJ
+0 -1.16 TD
+0.002 Tc
+0.02 Tw
+[(for)-5(c)2(es im)-5(ply )20(that th)18(e costs o)18(f)0( pr)-5(ovidi)24(ng pu)18(blic goods will no)18(t r)-5(e)-2(lat)20(e)-2( closely to the)]TJ
+0 -1.26 TD
+-0.001 Tw
+[(benefi)5(t)1(s i)5(ndi)5(vi)5(d)19(ual)5(s rec)23(e)-1(i)5(v)3(e fro)19(m)-4( the)19(m)-4(.)]TJ
+10.08 0 0 10.08 303.36 719.965 Tm
+0 Tc
+0 Tw
+(5)Tj
+12 0 0 12 99.36 689.36 Tm
+0.003 Tc
+0.179 Tw
+[(D)5(e)-1(spi)5(t)1(e these )20(di)5(ffi)5(cul)5(t)1(i)5(e)-1(s i)5(n)-1( )20(maki)5(ng a)19(n)-1( obj)5(ecti)5(ve)19( anal)5(ysi)5(s, g)19(o)-1(vern)19(ments )20(do i)5(n)]TJ
+0 -1.16 TD
+0.019 Tw
+[(fact )20(have )20(t)21(o)-1( )20(make)19( )20(deci)5(s)3(i)5(ons a)19(bout p)19(ubl)5(i)5(c)3( good)19( provi)5(s)3(i)25(on base)19(d)-1( on ass)23(e)-1(ssmen)19(ts)]TJ
+T*
+0.059 Tw
+[(of )20(thi)5(s)3( )20(pri)5(v)3(at)21(e, )20(subj)5(ec)23(ti)5(ve )20(i)5(n)-1(fo)19(rmati)5(on)19(. Thi)5(s)3( i)25(nevi)5(t)1(abl)5(y i)5(n)-1(v)23(o)-1(l)5(v)3(es soci)5(al)5( p)19(r)-4(ocesses)]TJ
+T*
+-0.001 Tw
+[(that are)19( i)5(n)-1(consi)5(s)3(te)19(nt, i)5(neffi)5(ci)5(e)19(n)-1(t and )20(possi)5(bl)5(y un)19(fai)5(r)-4(.)]TJ
+0 -2.3 TD
+[(P)10(eopl)5(e can r)16(e)-1(veal)5( thei)25(r pr)16(efere)19(n)-1(ces i)5(n)-1( tw)5(o)19( w)5(a)-1(ys:)]TJ
+0 -2.32 TD
+0.004 Tc
+0.078 Tw
+[(Fi)6(rst, dev)24(ol)6(uti)6(on al)6(l)6(o)0(w)6(s)4( )20(peopl)6(e)20( to \221)6(v)4(ote w)6(i)6(t)22(h thei)6(r)17( feet\222)6(.)2( I)22(f)2( bundl)26(es )-20(of )-20(tax)24(e)0(s )-20(and)]TJ
+0 -1.16 TD
+0.118 Tw
+[(publ)6(i)6(c)4( goods v)24(a)0(ry a)20(m)-3(ong j)26(u)0(ri)6(sdi)6(c)4(ti)6(ons,)22( peopl)6(e)20( can r)17(e)0(veal)6( th)20(ei)6(r )-20(pr)17(efer)17(ences )-20(by)]TJ
+0 -1.14 TD
+0.003 Tc
+0.059 Tw
+[(choosi)5(ng w)5(h)-1(e)19(r)-4(e th)19(ey l)5(i)5(v)3(e. T)14(h)-1(i)5(s)3( for)16(m)-4( of p)19(r)-4(efe)19(r)-4(ence )20(revel)5(a)-1(ti)5(o)19(n)-1( i)5(s)3( captu)19(r)-4(ed i)5(n)-1( the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(Ti)6(ebout )20(Model)6( )20(\(Ti)6(e)0(b)20(out, 1)20(956\).)22( It i)6(s)4( )-20(p)20(a)0(rti)6(c)4(ul)6(a)20(r)-3(l)6(y)4( )-20(effecti)6(v)4(e for )-20(d)20(e)0(ci)6(si)6(ons )-20(such as)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(choi)5(ces of scho)19(o)-1(l)5(.)1( It p)19(u)-1(ts pr)16(essure )20(on l)5(o)-1(cal)5( au)19(tho)19(r)-4(i)5(t)1(i)5(e)-1(s to )-20(of)21(fer )-20(p)19(ubl)5(i)5(c)3( )-20(goo)19(ds)]TJ
+T*
+0.219 Tw
+[(peopl)5(e )20(w)5(ant)21( )20(and )20(t)21(o)-1( be ef)21(fi)5(ci)5(ent. )20(The )20(mechani)5(s)23(m)-4( i)5(s)3( l)5(i)5(m)-4(i)5(t)1(ed )20(by the c)23(o)-1(sts of)]TJ
+T*
+0.06 Tw
+[(m)-5(obility, )20(the li)24(m)-5(i)4(ted nu)18(m)-5(b)-2(e)18(r)-5( of ch)18(oices available)18( and t)20(he m)-5(a)18(ny oth)18(e)-2(r)-5( lim)-5(itati)24(ons)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(on l)5(o)-1(cati)5(on c)23(hoi)5(ce, such)19( as j)5(ob l)5(o)-1(c)23(a)-1(ti)5(ons.)]TJ
+0 -2.32 TD
+0.339 Tw
+[(The seco)19(nd w)5(a)-1(y p)19(eopl)5(e r)16(e)-1(veal)5( th)19(ei)5(r p)19(r)-4(efer)16(ences i)5(s)3( th)19(roug)19(h soci)5(al)5( )-20(choi)5(c)23(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.498 Tw
+[(mechani)6(sms)24(.)2( P)11(eopl)6(e ex)24(press t)22(hei)6(r p)20(r)-3(efe)20(r)-3(ences )-20(t)22(h)0(rou)20(gh )-20(voti)6(ng)20( )-20(or )-20(di)26(rect)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(i)5(n)-1(vol)5(v)3(ement )20(i)25(n)-1( )20(pol)5(i)5(t)1(i)5(c)3(al)5( )20(p)19(r)-4(ocesses, )20(s)23(ubmi)5(ssi)5(ons)23(, l)5(obbyi)5(n)-1(g)19( etc. L)19(e)-1(ts l)5(ook fi)25(rst at)]TJ
+0 -1.14 TD
+[(these soci)5(al)5( ch)19(oi)5(ce mec)23(hani)5(sms )20(befor)16(e consi)5(d)-1(e)19(r)-4(i)5(ng )-20(u)19(nder )-20(w)25(hat )-20(ci)5(rcu)19(m)-4(stanc)23(es)]TJ
+0 -1.16 TD
+-0.021 Tw
+[(devol)5(uti)5(on may )-20(i)5(m)-4(p)19(r)-4(ove )-20(t)21(hem.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.004 Tc
+-0.002 Tw
+[(S)11(o)-5(cial C)6(h)15(oice )20(Mech)15(anism)13(s)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+0.119 Tw
+[(P)10(o)-1(l)5(i)5(t)1(i)5(c)3(al)5( or voti)5(ng )20(mechani)5(s)23(m)-4(s for)16( choosi)5(n)19(g l)5(e)-1(vel)5(s)3( of )20(publ)5(i)5(c)3( goo)19(ds )-20(ar)16(e )-20(al)5(w)5(a)-1(ys)]TJ
+0 -1.16 TD
+0.001 Tc
+0.221 Tw
+[(im)-6(per)-6(fect)19(. )20(A)8(r)-6(r)-6(o)-3(w\222s )20(I)19(m)-6(possibility )20(T)12(heor)14(em)-6( indica)17(tes tha)17(t)-1( no social)23( choice r)14(u)-3(le)]TJ
+0 -1.14 TD
+0.002 Tc
+0 Tw
+[(consi)4(s)2(tentl)4(y)2( sati)4(sfi)4(e)-2(s )20(basi)4(c)2( con)18(d)-2(i)4(t)0(i)4(ons.)]TJ
+0 -2.32 TD
+0.279 Tw
+[(A)10(n)-1(y unw)5(ei)5(ghted v)23(o)-1(ti)5(ng r)16(u)-1(l)5(e)-1( l)5(eads)23( to po)19(or soci)5(al)5( )20(deci)5(s)3(i)5(ons )-20(w)5(h)-1(e)19(n)-1( )-20(the)19(r)-4(e )-20(ar)16(e)]TJ
+0 -1.16 TD
+0.019 Tw
+[(di)5(fferences)23( i)5(n)-1( the i)25(n)-1(tensi)5(t)1(y of)21( pref)21(erenc)23(e. P)10(eopl)5(e w)5(i)5(t)21(h a l)5(a)-1(r)16(ge )-20(stake)19( )-20(i)5(n)-1( )-20(the )-20(i)5(ssu)19(e)]TJ
+T*
+0.119 Tw
+[(\(e.g.: )20(l)5(a)-1(n)19(dow)5(ne)19(rs )20(w)5(ho )20(mi)25(ght )20(hav)23(e to b)19(ear si)5(gni)5(fi)5(c)23(ant costs,)21( or p)19(eopl)5(e st)21(rongl)5(y)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(affected by)23( pol)5(l)5(u)-1(ti)5(on)19(\) have)19( the sa)19(me vot)21(e)-1(s as pe)19(opl)5(e w)5(i)5(t)1(h l)5(i)5(ttl)5(e )20(di)5(rect i)5(n)19(terest.)]TJ
+0 -2.32 TD
+0.14 Tw
+[(In )20(a )20(system)-5( )20(wit)20(h )20(m)-5(a)-2(jo)18(r)-5(i)4(ty )20(r)-5(u)-2(l)24(e)-2(, )20(the \221)24(m)-5(edian v)22(o)-2(ter)-5(\222)4( d)18(e)-2(ter)15(m)-5(ines th)18(e outco)18(m)-5(e)-2(. I)20(f)]TJ
+0 -1.16 TD
+0.039 Tw
+[(prefer)16(ences a)19(r)-4(e no)19(t \221)5(s)3(i)5(ngl)5(e pe)19(aked\222)5(, thi)5(s)23( can l)5(e)-1(a)19(d)-1( to pa)19(rti)5(c)3(ul)5(arl)5(y)3( )20(poor)16( )-20(deci)5(s)3(i)5(ons.)]TJ
+T*
+0.059 Tw
+[(On most i)5(ssu)19(es ther)16(e i)5(s)3( a sp)19(ectru)19(m)-4( of choi)5(c)23(e)-1(s abou)19(t how)5( m)16(u)-1(ch of the )-20(go)19(od )-20(to)]TJ
+0 -1.14 TD
+0.179 Tw
+[(provi)5(de. I)21(f)1( pre)19(f)1(ere)19(n)-1(ces ar)16(e si)5(ngl)5(e p)19(eaked, )20(the de)19(nsi)5(t)1(y )-20(functi)25(on )-20(has a )-20(si)5(ngl)5(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(maxi)6(mum )40(and )20(t)22(he )20(me)20(an, m)17(ode an)20(d me)20(di)6(an a)20(r)-3(e re)20(asonabl)6(y cl)26(osel)6(y rel)6(a)20(ted. O)22(n)]TJ
+0 -1.2 TD
+0.002 Tc
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 164.24 m
+99.366 164.24 l
+S
+BT
+12 0 0 12 200.16 160.16 Tm
+( )Tj
+ET
+243.843 164.24 m
+200.163 164.24 l
+S
+BT
+10.08 0 0 10.08 99.36 148.525 Tm
+0 Tc
+(5)Tj
+0.5476 -0.3095 TD
+-0.006 Tc
+0.228 Tw
+[( )-1762(Some )24(t)-14(heoret)-14(ical )24(mechanisms )24(will )24(lead t)-14(o)2( per)17(f)-14(e)2(ct)10( pref)-14(erence revelat)-14(ion.)-14( )24(T)-14(hese have)]TJ
+2.2619 -1.1667 TD
+-0.008 Tc
+0.159 Tw
+[(pr)-8(oblem)-8(s)-8(,)-16( )24(howev)-8(er)-8(,)-16( )24(bot)-16(h )48(t)-16(heor)-8(et)-16(ic)-8(ally)-8( )24(and in r)-8(ealit)-16(y)-8(.)-16( )24( I)-16(n)0(c)-8(ent)-16(iv)-8(e c)-8(o)24(m)-8(pat)-16(ible m)-8(e)0(c)-8(hanis)-8(m)-8(s)]TJ
+0 -1.1429 TD
+0.086 Tw
+[(s)-8(u)0(c)-8(h)0( as)-8( t)-16(he Clar)-8(k)-8(-)15(G)-16(r)-8(ov)-8(e )23(m)-8(e)0(c)-8(hanis)-8(m)-8( y)-8(ield r)-8(e)0(v)-8(enue t)-16(hat)-16( )23(c)-8(annot)-16( be us)-8(ed wit)-16(hout)-16( )23(v)-8(iolat)-16(ing)]TJ
+0 -1.1667 TD
+-0.006 Tc
+0.014 Tw
+[(incent)-14(ive compat)-14(ibilit)-14(y.)-14( )24(T)-14(hey are also vulnerable t)-14(o)2( manipulat)-14(ion )-24(\(T)-14(idemann )-24(and )-22(T)-14(ullock\).)]TJ
+0 -1.1429 TD
+-0.008 Tc
+0.063 Tw
+[(O)-16(n)0( t)-16(he pr)-8(ac)16(t)-16(i)0(c)-8(al s)-8(ide,)-16( bec)-8(aus)-8(e of)8( t)-16(heir)-8( c)-8(o)0(m)-8(plex)-8(it)-16(y)16(,)-16( )23(t)-16(hey)-8( ar)-8(e )-24(inf)-16(eas)-8(ible )-24(f)-16(o)0(r)-8( )-24(lar)-8(ge )-24(gr)-8(oups)-8( )-24(or)]TJ
+T*
+0.016 Tw
+[(lar)-8(ge num)-8(ber)-8(s)-8( of)-16( is)-8(s)-8(ues)-8(.)]TJ
+ET
+endstream endobj 160 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 161 0 obj << /Type /Page /Parent 152 0 R /Resources 163 0 R /Contents 162 0 R >> endobj 162 0 obj << /Length 27065 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(15)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.079 Tw
+[(some )20(i)5(ssues, )40(how)5(ever)16(, vote)19(r pre)19(f)1(erenc)23(es ar)16(e l)5(i)5(k)3(el)5(y to b)19(e)-1( doubl)25(e peake)19(d)-1(. On)19(e)]TJ
+0 -1.16 TD
+0.02 Tw
+[(gr)-5(oup o)18(f)0( peo)18(ple will pr)-5(ef)20(er)-5( a low lev)22(e)-2(l of p)18(r)-5(ovision )-20(a)18(nd )-20(an)18(other)-5( )-20(will )-20(p)18(r)-5(efe)18(r)-5( )-20(a )-20(hig)18(h)]TJ
+T*
+0.004 Tc
+0.038 Tw
+[(l)6(e)0(vel)6(.)2( )20( )20(Few)6( )20(p)20(eopl)6(e )20(w)6(a)20(nt an i)6(n)0(t)22(e)0(rm)17(edi)6(ate l)6(e)0(v)24(e)0(l)6( but t)22(h)0(i)6(s)4( i)6(s)4( the l)6(e)0(v)24(e)0(l)6( that i)6(s)4( ch)20(osen)]TJ
+T*
+0.002 Tc
+0 Tw
+[(in a majo)18(rity vote.)]TJ
+/F3 1 Tf
+0 -2.82 TD
+0.006 Tc
+-0.004 Tw
+[(Figur)15(e )20(2 S)13(i)4(ng)17(le an)17(d D)8(o)17(ubl)24(e P)13(eake)22(d P)13(r)15(efer)15(ence D)28(e)2(nsi)24(t)-1(y F)17(u)-3(n)17(c)2(tio)17(n)-3(s)]TJ
+ET
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+1 i
+128.16 592.16 m
+128.16 431.36 l
+S
+130.8 591.92 m
+128.16 596.96 l
+125.76 591.92 l
+130.8 591.92 l
+f*
+128.16 431.36 m
+504.96 431.36 l
+S
+504.72 428.72 m
+509.76 431.36 l
+504.72 433.76 l
+504.72 428.72 l
+f*
+BT
+/F5 1 Tf
+12 0 0 12 402.72 404.48 Tm
+0.003 Tc
+-0.001 Tw
+[(Quanti)5(t)1(y of publ)5(i)5(c)3( good)]TJ
+-24.6 0.6 TD
+0 Tc
+0 Tw
+(0)Tj
+21 13.8 TD
+0.004 Tc
+-0.002 Tw
+[(S)-9(i)6(ngl)6(e peaked)]TJ
+ET
+394.56 575.36 m
+355.44 548.96 l
+S
+354.24 551.36 m
+351.36 546.56 l
+357.12 547.28 l
+354.24 551.36 l
+f*
+BT
+12 0 0 12 453.12 512.48 Tm
+[(D)6(oubl)6(e peaked)]TJ
+ET
+495.36 503.36 m
+463.92 490.88 l
+S
+463.2 493.28 m
+459.36 488.96 l
+465.12 488.48 l
+463.2 493.28 l
+f*
+BT
+12 0 0 12 107.52 634.88 Tm
+0.003 Tc
+0.879 Tw
+[(N)5(o)-1(. of peopl)5(e )20(for)]TJ
+0 -1.16 TD
+0.004 Tc
+0.338 Tw
+[(w)6(hom thi)6(s)4( i)6(s)4( opti)6(m)17(al)]TJ
+0 -1.18 TD
+0.002 Tc
+(level)Tj
+-0.6 -2.46 TD
+(f\(Q\))Tj
+31.2 -13.2 TD
+0 Tc
+0 Tw
+(Q)Tj
+ET
+0.96 w
+315.36 589.76 m
+315.36 431.36 l
+S
+BT
+12 0 0 12 294.72 411.68 Tm
+0.005 Tc
+[(Medi)7(an)]TJ
+ET
+0.72 w
+348 552.32 m
+346.56 554.96 l
+344.88 557.36 l
+342.96 559.76 l
+339.12 564.08 l
+336.96 565.76 l
+334.8 567.68 l
+330 570.56 l
+325.2 572.96 l
+319.92 574.4 l
+317.28 574.88 l
+314.64 575.12 l
+311.76 575.36 l
+308.64 575.12 l
+305.52 574.64 l
+302.4 574.16 l
+299.28 573.2 l
+296.4 572 l
+293.52 570.56 l
+290.88 568.88 l
+285.6 565.04 l
+283.2 562.64 l
+281.04 560.24 l
+278.88 557.6 l
+276.96 554.72 l
+273.6 548.48 l
+272.16 545.12 l
+488.88 434.96 m
+487.92 434.72 l
+486.72 434.72 l
+481.44 434.24 l
+471.12 434.24 l
+466.08 434.48 l
+460.8 435.2 l
+455.76 435.92 l
+450.72 436.88 l
+445.92 438.08 l
+440.88 439.52 l
+436.08 441.2 l
+426.96 445.04 l
+417.84 449.84 l
+413.52 452.48 l
+409.2 455.36 l
+405.12 458.24 l
+401.28 461.36 l
+397.44 464.72 l
+393.6 468.32 l
+390 471.92 l
+386.64 475.76 l
+383.28 479.84 l
+380.16 483.92 l
+377.04 488.24 l
+369.12 501.92 l
+366.96 506.96 l
+364.8 511.76 l
+362.88 516.8 l
+361.2 522.08 l
+347.76 553.76 m
+362.16 517.76 l
+129.84 434.72 m
+130.8 434.72 l
+132 434.48 l
+137.28 434.24 l
+142.32 434 l
+152.88 434.48 l
+157.92 434.96 l
+168 436.88 l
+172.8 438.08 l
+177.84 439.52 l
+182.64 441.2 l
+191.76 445.04 l
+196.32 447.2 l
+200.88 449.84 l
+209.52 455.12 l
+213.6 458.24 l
+217.44 461.36 l
+221.28 464.72 l
+225.12 468.32 l
+228.72 471.92 l
+232.08 475.76 l
+235.44 479.84 l
+238.56 483.92 l
+241.68 488.24 l
+244.32 492.56 l
+246.96 497.36 l
+249.6 501.92 l
+251.76 506.72 l
+253.92 511.76 l
+255.84 516.8 l
+257.52 522.08 l
+272.16 546.56 m
+256.32 517.76 l
+S
+127.92 431.36 m
+127.92 431.12 l
+128.16 431.12 l
+128.16 430.88 l
+128.4 431.12 l
+128.64 431.12 l
+130.32 433.52 l
+130.32 433.76 l
+130.08 434 l
+129.84 434 l
+129.6 433.76 l
+127.92 431.36 l
+f
+131.04 435.44 m
+130.8 435.44 l
+130.8 435.2 l
+131.04 435.2 l
+131.04 434.96 l
+131.52 434.96 l
+131.52 435.2 l
+133.2 437.36 l
+133.44 437.6 l
+132.96 438.08 l
+132.72 437.84 l
+131.04 435.44 l
+f
+133.92 439.52 m
+133.92 439.28 l
+134.16 439.04 l
+134.4 439.04 l
+134.64 439.28 l
+136.32 441.44 l
+136.32 441.92 l
+135.6 441.92 l
+133.92 439.52 l
+f
+137.04 443.6 m
+137.04 443.12 l
+137.52 443.12 l
+139.2 445.52 l
+139.44 445.76 l
+139.2 446 l
+138.72 446 l
+137.04 443.6 l
+f
+139.92 447.68 m
+139.92 447.2 l
+140.16 447.2 l
+140.16 446.96 l
+140.4 446.96 l
+140.4 447.2 l
+140.64 447.2 l
+141.12 447.92 l
+142.32 449.6 l
+142.32 450.08 l
+141.84 450.08 l
+141.84 449.84 l
+140.4 448.4 l
+139.92 447.68 l
+f
+143.04 451.52 m
+143.04 451.28 l
+143.28 451.28 l
+143.28 451.04 l
+143.52 451.28 l
+143.76 451.28 l
+145.44 453.68 l
+145.44 453.92 l
+145.2 454.16 l
+144.96 454.16 l
+144.72 453.92 l
+143.04 451.52 l
+f
+146.16 455.6 m
+145.92 455.6 l
+145.92 455.36 l
+146.16 455.36 l
+146.16 455.12 l
+146.64 455.12 l
+146.64 455.36 l
+147.36 456.32 l
+148.32 457.52 l
+148.56 457.76 l
+148.08 458.24 l
+147.84 458 l
+146.88 456.56 l
+146.16 455.6 l
+f
+149.04 459.68 m
+149.04 459.2 l
+149.76 459.2 l
+151.44 461.6 l
+151.44 462.08 l
+150.96 462.08 l
+150.96 461.84 l
+149.04 459.68 l
+f
+152.16 463.76 m
+152.16 463.28 l
+152.4 463.28 l
+152.4 463.04 l
+152.64 463.04 l
+152.64 463.28 l
+152.88 463.28 l
+153.6 464.24 l
+154.56 465.68 l
+154.56 466.16 l
+154.08 466.16 l
+154.08 465.92 l
+153.12 464.72 l
+152.16 463.76 l
+f
+155.28 467.6 m
+155.28 467.36 l
+155.52 467.12 l
+155.76 467.12 l
+156 467.36 l
+157.68 469.52 l
+157.68 470 l
+156.96 470 l
+155.28 467.6 l
+f
+158.4 471.68 m
+158.4 471.2 l
+158.64 471.2 l
+158.64 470.96 l
+158.88 470.96 l
+158.88 471.2 l
+159.12 471.2 l
+159.84 472.16 l
+160.8 473.6 l
+160.8 473.84 l
+160.56 474.08 l
+160.32 474.08 l
+160.08 473.84 l
+159.12 472.64 l
+158.4 471.68 l
+f
+161.52 475.52 m
+161.52 475.28 l
+161.76 475.04 l
+162 475.04 l
+162.24 475.28 l
+163.92 477.44 l
+163.92 477.92 l
+163.44 477.92 l
+161.52 475.52 l
+f
+164.64 479.6 m
+164.64 479.12 l
+164.88 479.12 l
+164.88 478.88 l
+165.12 478.88 l
+165.12 479.12 l
+165.36 479.12 l
+165.84 479.84 l
+167.04 481.28 l
+167.28 481.52 l
+166.8 482 l
+166.56 481.76 l
+165.36 480.32 l
+164.64 479.6 l
+f
+168 483.44 m
+167.76 483.2 l
+168 482.96 l
+168.48 482.96 l
+170.4 485.36 l
+170.4 485.6 l
+170.16 485.84 l
+169.92 485.84 l
+169.68 485.6 l
+168 483.44 l
+f
+171.12 487.28 m
+171.12 486.8 l
+171.6 486.8 l
+172.08 487.28 l
+173.52 489.2 l
+173.52 489.68 l
+173.04 489.68 l
+173.04 489.44 l
+171.36 487.76 l
+171.12 487.28 l
+f
+174.24 491.12 m
+174.24 490.64 l
+174.96 490.64 l
+176.88 493.04 l
+176.88 493.28 l
+176.64 493.52 l
+176.4 493.52 l
+176.16 493.28 l
+174.24 491.12 l
+f
+177.6 494.96 m
+177.6 494.48 l
+178.32 494.48 l
+180.24 496.64 l
+180.24 497.12 l
+180 497.12 l
+180 497.36 l
+179.76 497.36 l
+179.76 497.12 l
+179.52 497.12 l
+177.6 494.96 l
+f
+180.96 498.8 m
+180.96 498.32 l
+181.2 498.32 l
+181.2 498.08 l
+181.44 498.08 l
+181.44 498.32 l
+181.68 498.32 l
+183.6 500.48 l
+183.6 500.96 l
+182.88 500.96 l
+180.96 498.8 l
+f
+184.32 502.4 m
+184.32 502.16 l
+184.56 501.92 l
+184.8 501.92 l
+186.96 504.08 l
+186.96 504.56 l
+186.72 504.56 l
+186.72 504.8 l
+186.48 504.8 l
+186.48 504.56 l
+186.24 504.56 l
+184.32 502.4 l
+f
+187.92 506 m
+187.68 506 l
+187.68 505.76 l
+187.92 505.76 l
+187.92 505.52 l
+188.4 505.52 l
+188.4 505.76 l
+189.84 507.2 l
+190.32 507.92 l
+190.56 507.92 l
+190.56 508.16 l
+190.32 508.16 l
+190.32 508.4 l
+189.84 508.4 l
+189.84 508.16 l
+189.12 507.44 l
+187.92 506 l
+f
+191.28 509.6 m
+191.28 509.36 l
+191.52 509.12 l
+191.76 509.12 l
+192.72 510.08 l
+192.24 510.32 l
+192.48 509.84 l
+194.16 511.52 l
+193.68 512 l
+191.28 509.6 l
+f
+195.12 513.44 m
+194.88 513.2 l
+194.88 512.96 l
+195.12 512.72 l
+195.36 512.72 l
+197.52 514.64 l
+197.76 514.88 l
+197.76 515.12 l
+197.52 515.36 l
+197.28 515.36 l
+195.12 513.44 l
+f
+198.72 516.8 m
+198.72 516.56 l
+198.48 516.56 l
+198.48 516.32 l
+198.72 516.32 l
+198.72 516.08 l
+199.2 516.08 l
+200.88 517.76 l
+201.36 518 l
+201.36 518.72 l
+200.88 518.72 l
+200.64 518.48 l
+198.72 516.8 l
+f
+202.56 520.16 m
+202.56 519.92 l
+202.32 519.92 l
+202.32 519.68 l
+202.56 519.68 l
+202.56 519.44 l
+203.04 519.44 l
+203.76 520.16 l
+205.2 521.36 l
+205.44 521.6 l
+204.96 522.08 l
+204.72 521.84 l
+203.28 520.64 l
+202.56 520.16 l
+f
+206.4 523.28 m
+206.4 522.56 l
+206.88 522.56 l
+209.04 524.24 l
+209.04 524.48 l
+209.28 524.48 l
+209.28 524.96 l
+208.8 524.96 l
+206.4 523.28 l
+f
+210.48 526.16 m
+210.48 525.68 l
+210.96 525.68 l
+211.68 526.16 l
+213.36 527.12 l
+213.36 527.36 l
+213.6 527.36 l
+213.6 527.6 l
+213.36 527.6 l
+213.36 527.84 l
+212.88 527.84 l
+211.44 526.88 l
+210.48 526.16 l
+f
+214.8 529.04 m
+214.8 528.8 l
+214.56 528.8 l
+214.56 528.56 l
+214.8 528.56 l
+214.8 528.32 l
+215.28 528.32 l
+216.96 529.28 l
+217.68 529.76 l
+217.68 530 l
+217.92 530 l
+217.44 530.48 l
+217.44 530.24 l
+216.72 530 l
+214.8 529.04 l
+f
+219.36 531.44 m
+219.12 531.2 l
+219.12 530.96 l
+219.36 530.72 l
+219.6 530.72 l
+222 531.68 l
+222.24 531.92 l
+222.48 531.92 l
+222.48 532.4 l
+222.24 532.4 l
+222.24 532.64 l
+222 532.64 l
+221.76 532.4 l
+219.36 531.44 l
+f
+224.16 533.36 m
+223.68 532.88 l
+223.92 532.64 l
+224.4 532.64 l
+226.8 533.12 l
+227.04 533.12 l
+227.04 533.36 l
+227.28 533.36 l
+227.28 533.84 l
+226.56 533.84 l
+224.16 533.36 l
+f
+228.96 534.32 m
+228.96 534.08 l
+228.72 534.08 l
+228.72 533.6 l
+231.6 533.6 l
+231.36 533.84 l
+231.36 533.6 l
+232.08 533.6 l
+232.32 533.84 l
+232.32 534.08 l
+232.08 534.32 l
+228.96 534.32 l
+f
+234.24 534.08 m
+234 534.08 l
+233.76 533.84 l
+233.76 533.6 l
+234 533.36 l
+235.92 533.12 l
+236.88 532.88 l
+237.12 532.88 l
+237.12 533.12 l
+237.36 533.12 l
+237.36 533.36 l
+237.12 533.36 l
+237.12 533.6 l
+236.88 533.6 l
+236.16 533.84 l
+234.24 534.08 l
+f
+239.04 532.88 m
+238.56 532.88 l
+238.56 532.4 l
+238.8 532.4 l
+238.8 532.16 l
+240.48 531.68 l
+241.68 531.2 l
+241.92 531.2 l
+241.92 531.92 l
+241.68 531.92 l
+240.72 532.4 l
+239.04 532.88 l
+f
+243.84 530.96 m
+243.36 530.96 l
+243.36 530.24 l
+244.8 529.76 l
+246 529.04 l
+246 528.8 l
+246.24 528.8 l
+246.24 529.04 l
+246.48 529.04 l
+246.48 529.52 l
+246.24 529.52 l
+243.84 530.96 l
+f
+248.16 528.32 m
+247.92 528.56 l
+247.68 528.32 l
+247.68 527.84 l
+249.12 527.12 l
+250.08 526.16 l
+250.56 526.16 l
+250.56 526.4 l
+250.8 526.4 l
+250.8 526.64 l
+250.56 526.64 l
+250.56 526.88 l
+248.16 528.32 l
+f
+252.24 525.44 m
+252.24 525.68 l
+252 525.68 l
+252 525.44 l
+251.76 525.44 l
+251.76 524.96 l
+252 524.96 l
+253.2 524 l
+254.16 523.04 l
+254.4 523.04 l
+254.64 523.28 l
+254.64 523.52 l
+254.4 523.76 l
+253.44 524.48 l
+252.24 525.44 l
+f
+256.08 522.32 m
+255.6 522.32 l
+255.6 521.84 l
+255.84 521.84 l
+257.28 520.64 l
+258 519.92 l
+258 519.68 l
+258.24 519.68 l
+258.24 519.92 l
+258.48 519.92 l
+258.48 520.4 l
+258.24 520.4 l
+257.52 521.12 l
+256.08 522.32 l
+f
+259.92 518.96 m
+259.44 518.96 l
+259.44 518.48 l
+261.6 516.32 l
+262.08 516.32 l
+262.08 516.56 l
+262.32 516.56 l
+262.32 516.8 l
+262.08 516.8 l
+262.08 517.04 l
+261.6 517.52 l
+259.92 518.96 l
+f
+263.52 515.6 m
+263.28 515.6 l
+263.04 515.36 l
+263.04 515.12 l
+265.2 512.96 l
+265.68 512.96 l
+265.92 513.2 l
+263.52 515.6 l
+f
+267.12 512 m
+266.88 512 l
+266.64 511.76 l
+266.64 511.52 l
+266.88 511.28 l
+268.8 509.6 l
+268.8 509.36 l
+269.28 509.36 l
+269.28 509.6 l
+269.52 509.6 l
+269.52 509.84 l
+269.28 509.84 l
+269.28 510.08 l
+269.04 510.08 l
+267.12 512 l
+f
+270.72 508.4 m
+270.72 508.64 l
+270.48 508.64 l
+270.48 508.4 l
+270.24 508.4 l
+270.24 507.92 l
+270.48 507.92 l
+272.4 506 l
+272.64 506 l
+272.64 505.76 l
+272.88 505.76 l
+272.88 506 l
+273.12 506 l
+273.12 506.48 l
+272.88 506.48 l
+270.72 508.4 l
+f
+274.56 505.04 m
+274.08 505.04 l
+273.84 504.8 l
+276 502.64 l
+276.24 502.64 l
+276.48 502.4 l
+276.72 502.64 l
+276.72 503.12 l
+276.48 503.36 l
+274.56 505.04 l
+f
+278.4 501.68 m
+277.92 501.68 l
+277.68 501.44 l
+277.92 501.2 l
+279.6 499.76 l
+280.32 499.28 l
+280.56 499.28 l
+280.8 499.52 l
+280.8 499.76 l
+280.56 500 l
+279.84 500.48 l
+278.4 501.68 l
+f
+282.48 498.8 m
+282 498.8 l
+282 498.56 l
+281.76 498.56 l
+281.76 498.32 l
+282 498.32 l
+282 498.08 l
+282.96 497.6 l
+284.4 496.64 l
+284.88 496.64 l
+284.88 496.88 l
+285.12 496.88 l
+285.12 497.12 l
+284.88 497.12 l
+284.88 497.36 l
+283.44 498.08 l
+282.48 498.8 l
+f
+286.8 496.4 m
+286.56 496.4 l
+286.32 496.16 l
+286.32 495.92 l
+286.56 495.92 l
+286.56 495.68 l
+289.2 494.72 l
+289.44 494.72 l
+289.68 494.96 l
+289.68 495.2 l
+289.44 495.44 l
+286.8 496.4 l
+f
+291.36 494.48 m
+291.12 494.48 l
+290.88 494.24 l
+291.36 493.76 l
+293.04 493.28 l
+294 492.8 l
+294.24 492.8 l
+294.24 493.52 l
+294 493.52 l
+293.04 494 l
+291.36 494.48 l
+f
+296.16 492.8 m
+295.92 492.8 l
+295.92 492.56 l
+295.68 492.56 l
+295.68 492.08 l
+295.92 492.08 l
+298.56 490.88 l
+298.8 490.88 l
+298.8 491.12 l
+299.04 491.12 l
+299.04 491.6 l
+298.8 491.6 l
+296.16 492.8 l
+f
+300.72 491.12 m
+300.48 490.88 l
+300.48 490.4 l
+300.72 490.4 l
+303.36 489.44 l
+303.84 489.44 l
+303.84 489.92 l
+303.6 489.92 l
+303.6 490.16 l
+300.72 491.12 l
+f
+305.52 489.44 m
+305.28 489.44 l
+305.28 489.2 l
+305.04 489.2 l
+305.04 488.96 l
+305.28 488.96 l
+305.28 488.72 l
+305.52 488.72 l
+306.96 488.24 l
+308.16 488 l
+308.4 488 l
+308.64 488.24 l
+308.64 488.48 l
+308.4 488.72 l
+306.96 488.96 l
+305.52 489.44 l
+f
+310.56 488.24 m
+310.32 488.24 l
+310.08 488 l
+310.08 487.76 l
+310.32 487.52 l
+312 487.04 l
+313.44 487.04 l
+313.44 487.28 l
+313.68 487.28 l
+313.68 487.52 l
+313.44 487.52 l
+313.44 487.76 l
+312.24 487.76 l
+310.56 488.24 l
+f
+315.36 487.52 m
+315.12 487.52 l
+315.12 486.8 l
+315.36 486.8 l
+317.04 486.56 l
+318.24 486.56 l
+318.72 487.04 l
+318.48 487.28 l
+317.04 487.28 l
+315.36 487.52 l
+f
+320.4 487.52 m
+320.16 487.28 l
+320.16 486.8 l
+322.08 486.8 l
+323.28 487.04 l
+323.52 487.04 l
+323.52 487.76 l
+323.28 487.76 l
+322.08 487.52 l
+320.4 487.52 l
+f
+325.44 488 m
+325.2 488 l
+324.96 487.76 l
+325.44 487.28 l
+327.12 487.76 l
+328.32 488 l
+328.56 488.24 l
+328.56 488.48 l
+328.32 488.72 l
+328.08 488.72 l
+327.12 488.48 l
+325.44 488 l
+f
+330.24 489.44 m
+330 489.44 l
+330 488.72 l
+330.24 488.72 l
+332.64 489.68 l
+333.12 489.92 l
+333.36 490.16 l
+332.88 490.64 l
+332.64 490.4 l
+332.4 490.4 l
+332.64 489.92 l
+332.4 490.4 l
+330.24 489.44 l
+f
+334.56 491.6 m
+334.56 491.36 l
+334.32 491.36 l
+334.32 491.12 l
+334.56 491.12 l
+334.56 490.88 l
+335.04 490.88 l
+335.52 491.12 l
+337.44 492.56 l
+337.68 492.8 l
+337.44 493.04 l
+336.96 493.04 l
+335.04 491.84 l
+334.56 491.6 l
+f
+338.88 494.24 m
+338.64 494.24 l
+338.64 493.76 l
+339.12 493.76 l
+341.04 495.2 l
+341.52 495.44 l
+341.52 496.16 l
+341.04 496.16 l
+340.8 495.92 l
+338.88 494.24 l
+f
+342.72 497.6 m
+342.72 497.36 l
+342.48 497.36 l
+342.48 497.12 l
+342.72 497.12 l
+342.72 496.88 l
+343.2 496.88 l
+343.92 497.6 l
+345.36 498.8 l
+345.36 499.28 l
+345.12 499.52 l
+344.88 499.28 l
+343.68 498.32 l
+342.72 497.6 l
+f
+346.56 500.72 m
+346.32 500.72 l
+346.32 500.24 l
+346.8 500.24 l
+348.96 502.16 l
+348.96 502.4 l
+349.2 502.4 l
+349.2 502.64 l
+348.96 502.64 l
+348.96 502.88 l
+348.48 502.88 l
+346.56 500.72 l
+f
+350.16 504.32 m
+349.92 504.32 l
+349.92 503.84 l
+350.16 503.84 l
+350.16 503.6 l
+350.4 503.6 l
+350.4 503.84 l
+352.56 505.76 l
+352.8 506 l
+352.32 506.48 l
+352.08 506.24 l
+352.32 506 l
+352.08 506.24 l
+350.16 504.32 l
+f
+353.52 507.68 m
+353.52 507.44 l
+353.76 507.2 l
+354 507.2 l
+356.16 509.36 l
+356.16 509.84 l
+355.92 510.08 l
+353.52 507.68 l
+f
+357.12 511.28 m
+357.12 511.04 l
+357.36 510.8 l
+357.6 510.8 l
+357.84 511.04 l
+358.08 511.52 l
+359.76 512.96 l
+359.76 513.44 l
+359.52 513.68 l
+357.12 511.28 l
+f
+360.72 515.12 m
+360.72 514.4 l
+361.2 514.4 l
+363.36 516.56 l
+363.36 516.8 l
+363.12 517.04 l
+362.88 517.04 l
+360.72 515.12 l
+f
+364.56 518.48 m
+364.32 518.48 l
+364.32 518 l
+364.56 518 l
+364.56 517.76 l
+364.8 517.76 l
+364.8 518 l
+366 518.96 l
+367.2 520.16 l
+366.96 520.4 l
+366.48 520.4 l
+365.52 519.68 l
+364.56 518.48 l
+f
+368.16 521.84 m
+368.16 521.36 l
+368.4 521.12 l
+368.64 521.36 l
+370.8 523.04 l
+371.04 523.04 l
+371.04 523.52 l
+370.8 523.52 l
+370.8 523.76 l
+370.56 523.76 l
+370.56 523.52 l
+368.16 521.84 l
+f
+372.24 524.72 m
+372 524.48 l
+372.24 524.24 l
+372.72 524.24 l
+373.2 524.48 l
+375.12 525.68 l
+375.12 525.92 l
+375.36 525.92 l
+375.36 526.16 l
+375.12 526.16 l
+375.12 526.4 l
+374.64 526.4 l
+372.96 525.2 l
+372.24 524.72 l
+f
+376.56 527.6 m
+376.32 527.36 l
+376.32 527.12 l
+376.56 526.88 l
+376.8 526.88 l
+377.28 527.12 l
+379.2 528.56 l
+379.44 528.56 l
+379.44 529.04 l
+379.2 529.04 l
+379.2 529.28 l
+378.96 529.28 l
+378.96 529.04 l
+378.72 529.04 l
+377.04 527.84 l
+376.56 527.6 l
+f
+380.64 530.24 m
+380.64 529.76 l
+381.12 529.76 l
+382.56 530.72 l
+383.52 531.2 l
+383.76 531.44 l
+383.76 531.68 l
+383.52 531.92 l
+383.28 531.92 l
+382.08 531.2 l
+380.64 530.24 l
+f
+384.96 532.88 m
+384.96 532.4 l
+385.2 532.16 l
+385.44 532.4 l
+385.68 532.4 l
+385.44 532.64 l
+385.44 532.4 l
+387.12 533.12 l
+387.84 533.36 l
+388.08 533.36 l
+388.08 533.6 l
+388.32 533.6 l
+388.32 533.84 l
+388.08 533.84 l
+388.08 534.08 l
+387.84 534.08 l
+386.88 533.84 l
+385.44 533.12 l
+385.2 533.12 l
+384.96 532.88 l
+f
+390 534.8 m
+389.52 534.32 l
+389.76 534.08 l
+391.68 534.08 l
+391.68 534.56 l
+391.68 534.08 l
+392.88 534.08 l
+393.12 534.32 l
+393.12 534.8 l
+390 534.8 l
+f
+395.04 534.8 m
+394.8 534.8 l
+394.8 534.56 l
+394.56 534.56 l
+394.56 534.08 l
+394.8 534.08 l
+395.28 533.84 l
+397.2 533.36 l
+398.16 533.36 l
+398.16 533.84 l
+397.92 533.84 l
+397.92 534.08 l
+397.44 534.08 l
+395.28 534.56 l
+395.04 534.8 l
+f
+399.84 533.36 m
+399.6 533.36 l
+399.6 533.12 l
+399.36 533.12 l
+399.36 532.88 l
+399.6 532.88 l
+399.6 532.64 l
+399.84 532.64 l
+401.76 531.68 l
+402.48 531.44 l
+402.72 531.44 l
+402.72 532.16 l
+402.48 532.16 l
+402 532.4 l
+399.84 533.36 l
+f
+404.4 531.2 m
+404.16 531.2 l
+404.16 530.96 l
+403.92 530.96 l
+403.92 530.72 l
+404.16 530.72 l
+404.16 530.48 l
+404.4 530.48 l
+404.4 530.72 l
+404.16 530.48 l
+406.56 529.04 l
+407.04 529.04 l
+407.28 529.28 l
+407.04 529.52 l
+404.64 531.2 l
+404.4 531.2 l
+f
+408.72 528.32 m
+408.72 528.56 l
+408.48 528.56 l
+408.48 528.32 l
+408.24 528.32 l
+408.24 527.84 l
+408.48 527.84 l
+409.92 526.88 l
+410.88 526.16 l
+411.12 526.16 l
+411.36 526.4 l
+411.36 526.64 l
+411.12 526.88 l
+410.4 527.36 l
+408.72 528.32 l
+f
+413.04 525.44 m
+412.8 525.68 l
+412.32 525.2 l
+413.04 524.48 l
+414.72 523.04 l
+415.2 523.04 l
+415.2 523.28 l
+415.44 523.28 l
+415.44 523.52 l
+415.2 523.52 l
+415.2 523.76 l
+413.52 525.2 l
+413.04 525.44 l
+f
+416.88 522.32 m
+416.88 522.56 l
+416.64 522.56 l
+416.64 522.32 l
+416.4 522.32 l
+416.4 521.84 l
+416.64 521.84 l
+418.8 519.92 l
+419.04 519.92 l
+419.28 520.16 l
+419.28 520.4 l
+419.04 520.64 l
+416.88 522.32 l
+f
+420.72 519.2 m
+420.48 519.2 l
+420.24 518.96 l
+420.24 518.72 l
+420.48 518.48 l
+422.64 516.8 l
+422.64 516.56 l
+422.88 516.56 l
+422.88 516.8 l
+423.12 516.8 l
+423.12 517.28 l
+422.88 517.28 l
+420.72 519.2 l
+f
+424.56 515.84 m
+424.08 515.84 l
+424.08 515.36 l
+424.32 515.36 l
+426.48 513.44 l
+426.48 513.2 l
+426.72 513.2 l
+426.72 513.44 l
+426.96 513.44 l
+426.96 513.92 l
+426.72 513.92 l
+424.56 515.84 l
+f
+428.4 512.48 m
+427.92 512.48 l
+427.68 512.24 l
+430.08 509.84 l
+430.32 509.84 l
+430.56 510.08 l
+430.56 510.32 l
+428.4 512.48 l
+f
+432 509.12 m
+431.76 509.12 l
+431.52 508.88 l
+431.52 508.64 l
+433.68 506.48 l
+434.16 506.48 l
+434.16 506.72 l
+434.4 506.72 l
+434.4 506.96 l
+434.16 506.96 l
+434.16 507.2 l
+433.68 507.68 l
+432 509.12 l
+f
+435.6 505.52 m
+435.6 505.76 l
+435.36 505.76 l
+435.36 505.52 l
+435.12 505.52 l
+435.12 505.04 l
+435.36 505.04 l
+437.52 502.88 l
+438 503.36 l
+437.76 503.6 l
+435.6 505.52 l
+f
+439.2 502.16 m
+438.96 502.16 l
+438.72 501.92 l
+438.72 501.68 l
+439.92 500.48 l
+441.12 499.52 l
+441.36 499.52 l
+441.6 499.76 l
+441.6 500 l
+440.4 501.2 l
+439.2 502.16 l
+f
+443.04 498.56 m
+442.56 498.56 l
+442.32 498.32 l
+444.72 495.92 l
+444.96 495.92 l
+445.2 496.16 l
+445.2 496.4 l
+443.04 498.56 l
+f
+446.4 494.96 m
+446.4 495.2 l
+446.16 495.2 l
+446.16 494.96 l
+445.92 494.96 l
+445.92 494.48 l
+446.16 494.48 l
+446.4 494.24 l
+448.08 492.32 l
+448.56 492.32 l
+448.56 492.56 l
+448.8 492.56 l
+448.8 492.8 l
+448.56 492.8 l
+448.56 493.04 l
+446.64 494.96 l
+446.4 494.96 l
+f
+450.24 491.36 m
+450 491.6 l
+449.76 491.6 l
+449.52 491.36 l
+449.52 491.12 l
+451.92 488.72 l
+452.4 489.2 l
+450.24 491.36 l
+f
+453.84 487.76 m
+453.6 488 l
+453.36 488 l
+453.12 487.76 l
+453.12 487.52 l
+455.04 485.36 l
+455.28 485.36 l
+455.28 485.12 l
+455.52 485.12 l
+455.52 485.36 l
+455.76 485.36 l
+455.76 485.84 l
+453.84 487.76 l
+f
+457.2 484.16 m
+456.96 484.4 l
+456.48 483.92 l
+458.64 481.76 l
+458.64 481.52 l
+459.12 481.52 l
+459.12 482 l
+457.92 483.44 l
+457.2 484.16 l
+f
+460.56 480.32 m
+460.56 480.56 l
+460.08 480.56 l
+460.08 480.32 l
+459.84 480.32 l
+459.84 480.08 l
+460.08 480.08 l
+462 477.92 l
+462 477.68 l
+462.48 477.68 l
+462.48 478.16 l
+460.56 480.32 l
+f
+463.92 476.48 m
+463.68 476.72 l
+463.44 476.72 l
+463.2 476.48 l
+463.2 476.24 l
+465.12 474.08 l
+465.36 473.84 l
+465.6 473.84 l
+465.84 474.08 l
+465.84 474.32 l
+463.92 476.48 l
+f
+467.04 472.64 m
+467.04 472.88 l
+466.56 472.88 l
+466.56 472.4 l
+467.52 471.2 l
+468.24 470.24 l
+468.48 470 l
+468.72 470 l
+468.96 470.24 l
+468.96 470.48 l
+468 471.68 l
+467.04 472.64 l
+f
+470.16 468.8 m
+470.16 469.04 l
+469.68 469.04 l
+469.68 468.56 l
+471.36 466.16 l
+471.6 466.16 l
+471.6 465.92 l
+471.84 465.92 l
+471.84 466.16 l
+472.08 466.16 l
+472.08 466.64 l
+470.16 468.8 l
+f
+473.52 464.96 m
+472.8 464.96 l
+472.8 464.48 l
+474.48 462.32 l
+474.72 462.08 l
+474.96 462.08 l
+475.2 462.32 l
+475.2 462.56 l
+473.52 464.96 l
+f
+476.4 460.88 m
+476.4 461.12 l
+475.92 461.12 l
+475.92 460.64 l
+476.64 459.68 l
+477.6 458.24 l
+477.84 458.24 l
+477.84 458 l
+478.08 458 l
+478.08 458.24 l
+478.32 458.24 l
+478.32 458.72 l
+477.12 459.92 l
+476.4 460.88 l
+f
+479.52 456.8 m
+479.52 457.04 l
+479.04 457.04 l
+479.04 456.56 l
+480.72 454.4 l
+480.96 454.16 l
+481.2 454.16 l
+481.44 454.4 l
+481.44 454.64 l
+479.52 456.8 l
+f
+482.64 452.96 m
+482.4 453.2 l
+482.16 452.96 l
+482.16 452.48 l
+482.64 451.76 l
+483.84 450.32 l
+484.08 450.32 l
+484.08 450.08 l
+484.32 450.08 l
+484.32 450.32 l
+484.56 450.32 l
+484.56 450.8 l
+483.36 452.24 l
+482.64 452.96 l
+f
+485.76 449.12 m
+485.28 449.12 l
+485.28 448.64 l
+486.24 447.44 l
+487.2 446.48 l
+487.2 446.24 l
+487.68 446.24 l
+487.68 446.72 l
+486.96 447.68 l
+485.76 449.12 l
+f
+489.12 445.28 m
+488.64 445.28 l
+488.4 445.04 l
+488.64 444.8 l
+489.36 443.84 l
+490.8 442.4 l
+491.04 442.64 l
+491.04 443.12 l
+490.08 444.08 l
+489.12 445.28 l
+f
+492.48 441.44 m
+492.48 441.68 l
+492 441.68 l
+492 441.44 l
+491.76 441.44 l
+491.76 441.2 l
+492 441.2 l
+492.24 440.72 l
+493.92 439.04 l
+493.92 438.8 l
+494.4 438.8 l
+494.4 439.04 l
+494.64 439.04 l
+494.64 439.28 l
+494.4 439.28 l
+493.92 440 l
+492.48 441.44 l
+f
+496.08 437.84 m
+495.84 437.84 l
+495.84 438.08 l
+495.6 438.08 l
+495.6 437.84 l
+495.36 437.84 l
+495.36 437.36 l
+495.6 437.36 l
+497.52 435.44 l
+497.76 435.44 l
+497.76 435.2 l
+498 435.2 l
+498 435.44 l
+498.24 435.44 l
+498.24 435.92 l
+498 435.92 l
+496.08 437.84 l
+495.84 437.6 l
+496.08 437.84 l
+f
+499.68 434.48 m
+499.2 434.48 l
+498.96 434.24 l
+500.4 432.8 l
+501.36 432.08 l
+501.6 431.84 l
+501.84 432.08 l
+501.84 432.56 l
+500.64 433.52 l
+499.68 434.48 l
+f
+BT
+12 0 0 12 99.36 370.64 Tm
+0.003 Tc
+0.039 Tw
+[(A)10(n)-1( )20(i)5(ndi)5(vi)5(dual)5( coul)5(d )20(al)5(so have )20(doubl)5(e)19(-)-4(peak)23(ed pr)16(efer)16(ences. A)10(n)-1( ex)23(ampl)5(e )20(may be)]TJ
+0 -1.16 TD
+0.099 Tw
+[(sew)5(age cont)21(rol)5( i)5(n)-1( a ci)5(ty)23(. If sew)5(a)19(ge i)5(s)3( )-20(po)19(orl)5(y)3( )-20(tre)19(a)-1(ted, peopl)5(e )-20(si)25(mpl)5(y)3( )-20(do)19(n\222)5(t )-20(use)]TJ
+T*
+0.139 Tw
+[(the )20(beach)19(.)1( )20( )20(Me)19(di)5(ocre )20(co)19(ntrol)5( )20(has som)16(e)-1( cost bu)19(t i)5(s)3( i)5(n)-1(suffi)5(ci)5(e)19(n)-1(t to al)5(l)5(o)-1(w)5( )20(beach)]TJ
+T*
+0.119 Tw
+[(use so i)5(s)3( of n)19(o)-1( val)5(ue t)21(o)-1( ma)19(ny )-20(peopl)25(e. )-20( )-20(H)5(o)-1(w)5(e)-1(ve)19(r, )-20(excel)5(l)5(e)19(nt )-20(sew)5(age)19( )-20(trea)19(tment)]TJ
+0 -1.14 TD
+0.059 Tw
+[(w)5(oul)5(d al)5(l)5(o)-1(w)5( ful)5(l)5( use )20(of the)19( coast so )20(peopl)5(e w)25(oul)5(d )-20(val)5(u)19(e )-20(i)5(t. )-20( )-20(A)10(n)-1( )-20(i)5(ndi)5(vi)5(du)19(al)5( )-20(w)5(oul)5(d)]TJ
+0 -1.16 TD
+0.004 Tc
+0.258 Tw
+[(ei)6(ther p)20(r)-3(efer)17( no sew)6(e)20(rage)20( contr)17(o)0(l)6(,)2( or v)24(e)0(ry go)20(od cont)22(rol)6(.)2( )20(Medi)6(ocr)17(e)0( cont)22(rol)6(,)]TJ
+T*
+0 Tc
+0.002 Tw
+[(h)-4(o)-4(w)2(e)-4(v)0(e)-4(r)-7(, is t)18(h)-4(e)-4( le)-4(ve)-4(l t)18(h)-4(a)-4(t)-2( will b)-4(e)-4( ch)16(o)-4(s)0(e)-4(n)-4( in)-4( )20(a)-4( )-20(m)-7(a)-4(jo)16(r)-7(i)2(ty )-20(vo)-4(te)-4(. )-20(In)-4( )-20(ca)-4(se)-4(s)20( )-20(with)-4( )-20(d)-4(o)-4(u)16(b)-4(l)2(e)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(peaked p)19(r)-4(efe)19(r)-4(ences, )20(maj)5(o)-1(ri)5(ty)23( voti)5(ng )20(may l)5(ead)19( to an )20(outco)19(me that)21( no on)19(e w)5(ants.)]TJ
+0 -2.3 TD
+0.04 Tw
+[(A)9(nother)-5( )20(co)18(m)-5(m)-5(on )20(pr)-5(obl)24(em)-5( with )20(m)-5(a)-2(jor)-5(i)4(ty v)22(o)-2(ting is th)18(at wher)15(e \221voting cycl)24(es\222 exist)]TJ
+0 -1.16 TD
+0.004 Tc
+0.158 Tw
+[(\(no one)20( opti)6(o)0(n)20( i)6(s)4( pref)22(erre)20(d by a )20(maj)6(o)0(ri)6(ty)24( to )-20(al)6(l)6( )-20(ot)22(hers )-20(i)6(n)0( pai)6(rw)6(i)6(s)4(e )-20(vo)20(tes\), )-20(t)22(h)0(e)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(outcome i)5(n)19( a seri)25(es of vot)21(e)-1(s may )20(depen)19(d on th)19(e or)16(der )-20(i)5(n)-1( )-20(w)25(h)-1(i)5(c)3(h )-20(voti)5(ng)19( )-20(occurs.)]TJ
+T*
+-0.001 Tw
+[(Thi)5(s)3( mea)19(n)-1(s that w)25(hoeve)19(r)-4( sets th)19(e age)19(nda has )20(consi)5(d)-1(e)19(r)-4(abl)5(e p)19(o)-1(w)5(e)-1(r.)]TJ
+0 -2.3 TD
+0.159 Tw
+[(In )20(real)5(i)5(t)1(y )20(w)5(e)-1( )40(do )20(not)21( )20(vote )20(o)19(n)-1( )20(every)23( i)5(ssue. W)7(e)-1( vo)19(te fo)19(r agen)19(ts w)5(ho m)16(a)-1(ke the)]TJ
+0 -1.16 TD
+0.139 Tw
+[(detai)5(l)5(ed deci)5(s)3(i)5(o)19(ns on o)19(u)-1(r b)19(ehal)5(f. W)7(h)-1(e)19(n)-1( the)19(r)-4(e i)5(s)3( a w)5(i)5(d)19(e ran)19(ge of i)5(ssu)19(es, any)]TJ
+T*
+0.199 Tw
+[(agent i)5(s)3( unl)5(i)5(k)3(el)5(y )20(to tr)16(ul)5(y rep)19(r)-4(esent )20(any i)5(ndi)5(vi)5(d)19(ual)5(\222)5(s)3( basket )20(of )-20(pr)16(efer)16(ences )-20(l)5(e)-1(t)]TJ
+T*
+0.099 Tw
+[(al)5(one )20(the )40(pref)21(erences)23( )20(of )20(soci)5(ety)23( )20(as a w)5(hol)25(e. In a)19( l)5(a)-1(rge)19( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on)19(, each v)23(o)-1(te)]TJ
+T*
+-0.001 Tw
+[(has l)5(i)5(ttl)5(e i)5(m)-4(pac)23(t.)]TJ
+ET
+endstream endobj 163 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 164 0 obj << /Length 6651 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(16)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.079 Tw
+[(S)10(o)-1(ci)5(al)5( )20(choi)5(ce )20(i)5(s)3( cl)5(earl)5(y)3( a)19(n)-1( i)5(nexact)21( proc)23(ess. Th)19(e key i)5(ssue)19( of rel)25(e)-1(vance t)21(o)-1( thi)5(s)]TJ
+0 -1.16 TD
+0.119 Tw
+[(paper i)5(s)3( w)5(h)19(ether)16( devol)5(uti)25(on i)5(m)-4(p)19(r)-4(oves soci)5(al)5( ch)19(oi)5(ce m)16(e)-1(chani)5(s)23(m)-4(s and )-20(l)5(e)19(ads )-20(to)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(better p)20(r)-3(efe)20(r)-3(ence )20(revel)6(a)0(ti)26(on.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.005 Tc
+[(W)9(h)-4(en d)16(o)-4(es D)27(evol)23(u)-4(ti)23(on Im)14(pr)14(o)16(ve S)12(o)-4(ci)23(al C)7(h)16(oice?)]TJ
+/F5 1 Tf
+0 -2.14 TD
+0.002 Tc
+0.5 Tw
+[(Will devolution m)-5(e)18(an tha)18(t)0( individual )20(pr)-5(efe)18(r)-5(ences)22( ar)-5(e )20(bette)18(r)-5( r)-5(e)-2(flec)22(ted )-20(in)]TJ
+0 -1.16 TD
+0.004 Tc
+0.058 Tw
+[(deci)6(s)4(i)6(ons? )20( )40(The )20(answ)26(e)0(r )20(i)6(s)4( no)20(t si)6(mpl)6(e)0(. )20( S)11(o)0(meti)6(mes)24( l)6(o)0(cal)6( gov)24(ernm)17(ent i)6(s)4( a )20(bette)20(r)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(deci)5(s)3(i)5(on-m)16(a)-1(ker; )20(s)23(o)-1(meti)5(m)16(e)-1(s )20(cent)21(ral)5( )20(gove)19(r)-4(nm)16(ent )20(i)5(s)3(. It)21( depe)19(nds on t)21(he det)21(ai)5(l)5(s)3( of)]TJ
+T*
+[(the )20(i)5(ssue un)19(der c)23(onsi)5(der)16(ati)5(on. W)7(h)19(at the f)21(o)-1(l)5(l)5(o)-1(w)5(i)5(ng sub)19(-)-4(secti)5(ons )20(ai)5(m to )20(uncove)19(r)]TJ
+T*
+0.004 Tc
+0.158 Tw
+(are the )Tj
+12 0 2.551 12 144.24 605.6 Tm
+-0.021 Tc
+[(cr)-28(i)-19(t)-23(e)-25(r)-28(ia)]TJ
+12 0 0 12 180 605.6 Tm
+0.003 Tc
+0.159 Tw
+[( that i)5(t)1( )20(depen)19(ds on. W)7(h)19(at ar)16(e the )20(pri)5(n)-1(ci)5(pl)5(es )-20(f)21(o)-1(r )-20(soci)5(al)5( )-20(c)23(hoi)5(ce)]TJ
+-6.72 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(mechani)6(sms)24( w)6(o)0(rki)6(ng w)26(e)0(l)6(l)6(?)]TJ
+0 -2.36 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(e)-1( have i)5(denti)5(f)1(i)25(ed th)19(ree p)19(r)-4(i)5(n)-1(ci)5(pl)5(es fo)19(r effi)5(ci)5(en)19(t deci)5(s)3(i)5(on )20(maki)5(ng:)]TJ
+0 -2.3 TD
+0 Tc
+0 Tw
+(1)Tj
+12 0 2.551 12 127.68 536 Tm
+0.004 Tc
+-0.002 Tw
+[(Inform)17(ed deci)6(s)4(i)6(o)0(n)20( maki)6(ng)]TJ
+12 0 0 12 127.68 522.08 Tm
+0.003 Tc
+0.459 Tw
+[(The )20(best)21( )20(deci)5(s)3(i)5(ons )40(refl)5(ect )40(al)5(l)5( the r)16(e)-1(l)5(e)-1(vant )20(obj)5(ecti)5(ve a)19(nd subj)5(ecti)5(v)23(e)]TJ
+0 -1.16 TD
+0.004 Tc
+[(informati)26(on.)]TJ
+-2.36 -2.3 TD
+0 Tc
+0 Tw
+(2)Tj
+12 0 2.551 12 127.68 480.56 Tm
+0.003 Tc
+-0.001 Tw
+[(B)10(a)-1(l)5(anced deci)5(s)3(i)5(on )20(maki)5(ng)]TJ
+12 0 0 12 127.68 466.64 Tm
+[(The best)21( deci)5(s)3(i)5(ons t)21(a)-1(ke i)5(n)-1(to )20(account c)23(o)-1(sts and)19( bene)19(fi)5(ts.)]TJ
+-2.36 -2.32 TD
+0 Tc
+0 Tw
+(3)Tj
+12 0 2.551 12 127.68 438.8 Tm
+0.002 Tc
+[(C)4(o)-2(st effecti)4(v)2(en)18(ess)]TJ
+12 0 0 12 127.68 424.88 Tm
+0.079 Tw
+[(D)5(upl)5(i)5(c)3(ati)5(on shoul)25(d be av)23(oi)5(ded w)5(h)19(ere d)19(e)-1(ci)5(si)5(on-m)16(a)-1(ki)5(ng costs)23( )-20(are hi)5(gh )-20(an)19(d)]TJ
+0 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(prefer)17(ences a)20(r)-3(e ho)20(moge)20(neous.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 383.12 Tm
+0.006 Tc
+-0.004 Tw
+[(Infor)15(m)15(e)2(d )20(decis)22(i)4(on)17( m)15(akin)17(g)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 356.96 Tm
+0.003 Tc
+-0.001 Tw
+[(Good deci)5(s)3(i)5(ons)23( refl)5(ect)21( al)5(l)5( the )20(rel)5(e)-1(vant)21( obj)5(ecti)5(ve )20(and su)19(bj)5(ecti)5(ve i)5(n)-1(fo)19(rmati)5(o)19(n)-1(.)]TJ
+0 -2.3 TD
+0.379 Tw
+[(P)10(eopl)5(e reveal)5( )20(thei)5(r s)23(ubj)5(ecti)5(ve p)19(r)-4(efe)19(r)-4(ences )20(by parti)5(ci)25(pati)5(ng i)5(n)-1( the )-20(pol)5(i)5(t)1(i)5(c)3(al)]TJ
+0 -1.16 TD
+0.139 Tw
+[(processes )20(i)5(n)19( )20(thei)5(r )20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons. )40( )20(If deci)5(s)3(i)5(o)19(ns are )20(made)19( by j)5(u)-1(ri)5(sdi)5(c)3(ti)25(ons that)21( do)]TJ
+T*
+0.119 Tw
+[(not )20(i)5(n)-1(cl)5(ude )40(al)5(l)5( )20(affecte)19(d)-1( )20(peo)19(pl)5(e, the)19(r)-4(e i)5(s)3( no)19( mecha)19(n)-1(i)5(s)3(m fo)19(r the )20(affecte)19(d)-1( peopl)25(e)]TJ
+T*
+0.079 Tw
+[(outsi)5(de the)19( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on)19( to r)16(e)-1(veal)5( thei)25(r pr)16(efere)19(n)-1(ces. Thus, )-20(w)5(h)19(en )-20(the )-20(j)25(u)-1(ri)5(sdi)5(c)3(ti)5(on)]TJ
+0 -1.14 TD
+0.004 Tc
+0.458 Tw
+[(i)6(s)4( )20(smal)6(l)6(e)0(r )20(th)20(an )20(the )40(area)20( )20(of the)20( exter)17(nal)6(i)6(t)2(i)6(e)0(s, eve)20(n)0( w)6(i)6(t)2(h be)20(ni)6(gn pol)6(i)6(t)2(i)6(c)4(al)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.003 Tw
+[(p)-5(r)-8(o)-5(c)-1(e)-5(sse)-5(s, )20(n)-5(o)-5(t)-3( a)-5(ll p)15(r)-8(e)-5(f)-3(e)15(r)-8(e)-5(n)-5(c)-1(e)-5(s)-1( will b)-5(e)-5( )20(r)-8(e)-5(fle)-5(c)-1(t)17(e)-5(d)-5( in)-5( d)15(e)-5(cisio)-5(n)-5(s)-1(.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.019 Tw
+[(The i)5(m)-4(p)19(o)-1(rta)19(n)-1(ce of su)19(bj)5(ecti)5(ve p)19(r)-4(efer)16(ences i)5(n)-1( m)16(a)-1(ki)5(ng effi)5(ci)5(ent )-20(d)19(e)-1(ci)5(si)5(ons )-20(de)19(pends)]TJ
+0 -1.16 TD
+0.159 Tw
+[(on the n)19(a)-1(ture)19( of the)19( i)5(ssue. In)19( some i)5(s)3(s)23(ues mos)23(t)1( bene)19(fi)5(ts are)19( subj)5(ecti)5(ve, )20(for)]TJ
+0 -1.14 TD
+0.079 Tw
+[(exampl)5(e, t)21(he nu)19(mber)16( of tr)16(ees i)5(n)-1( a)19(n)-1( are)19(a)-1(, pr)16(eservati)25(on of t)21(he hi)5(sto)19(r)-4(i)5(c)3( char)16(acter)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(of an ar)17(ea. P)11(r)-3(e)20(f)2(erenc)24(es on t)22(hese i)6(ssues)24( are l)6(i)6(k)4(el)6(y )20(to )-20(be )-20(v)24(e)0(ry )-20(he)20(tero)20(geneo)20(us.)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(In )20(other)16( )20(i)5(ssues, )20(th)19(e )20(ben)19(efi)5(t)1(s )20(ar)16(e mo)19(re obj)5(ecti)5(ve)19(, for)16( exam)16(pl)5(e, heal)5(t)21(h)-1( effects)23( fro)19(m)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(l)6(o)0(cal)6( ai)6(r pol)6(l)6(u)0(ti)26(on. E)11(ducat)22(ed pr)17(efer)17(ences on)20( these i)6(s)4(s)24(ues ar)17(e )-20(l)6(i)6(k)4(el)6(y )-20(to )-20(b)20(e)0( )-20(mo)20(re)]TJ
+T*
+[(homoge)20(neous.)]TJ
+0 -2.3 TD
+0.078 Tw
+[(If )20(the )20(deci)6(s)4(i)6(o)20(n-maki)26(ng )20(j)6(u)0(ri)6(sdi)6(c)4(ti)26(on )20(i)6(s)4( )20(l)6(a)0(r)17(ger t)22(han th)20(e are)20(a)0( w)6(her)17(e effects)24( are f)22(e)0(l)6(t)2(,)]TJ
+0 -1.16 TD
+0.138 Tw
+[(prefer)17(ences )20(ca)20(n )20(be )40(reveal)6(ed)20( )20(but ot)22(her )20(probl)6(em)17(s ari)6(s)24(e. If ce)20(ntral)6( g)20(o)0(vern)20(ment)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(makes pol)5(i)5(cy i)5(t)1( t)21(ends to)19( have o)19(ne pol)5(i)5(cy, w)25(h)-1(i)5(c)3(h appl)5(i)5(e)-1(s )20(to )-20(the enti)5(r)-4(e)19( )-20(count)21(ry)]TJ
+ET
+endstream endobj 165 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 166 0 obj << /Length 7601 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(17)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.119 Tw
+[(even w)5(her)16(e mul)5(t)1(i)5(p)-1(l)5(e)19( pol)5(i)5(c)3(i)5(e)-1(s a)19(r)-4(e possi)5(bl)25(e. For)16( pe)19(rcei)5(ved )20(equi)5(ty r)16(easons, )-20(i)5(t)21( )-20(i)5(s)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(di)6(ffi)6(cul)6(t)2( )20(for )20(c)24(entral)6( )40(gover)17(nment)22( to di)6(ffe)20(renti)6(a)20(te pol)6(i)6(c)4(i)6(e)0(s. )20(It w)6(oul)6(d )20(be even)20( mor)17(e)]TJ
+T*
+-0.002 Tw
+[(di)6(ffi)6(cul)6(t)2( for c)24(entral)6( )20(gover)17(nment)22( to tax di)6(ffere)20(ntl)6(y)4( )-20(i)6(n)0( )-20(di)6(ffe)20(rent areas)24(. )-20( )-20(P)11(eopl)6(e )-20(w)6(o)20(ul)6(d)]TJ
+T*
+0.003 Tc
+0.139 Tw
+[(not )20(make )40(a )20(cl)5(ear)16( )20(connecti)25(on betw)25(een th)19(e vari)5(a)19(n)-1(ce i)5(n)-1( tax )20(and th)19(e vari)5(a)19(n)-1(ce i)5(n)]TJ
+0 -1.14 TD
+0.004 Tc
+0.338 Tw
+[(regul)6(ati)6(ons)24( and )20(publ)6(i)6(c)4( servi)6(c)24(es. C)6(entr)17(a)0(l)6( gove)20(r)-3(nme)20(n)0(t has )20(a )-20(hete)20(r)-3(oge)20(neous)]TJ
+0 -1.16 TD
+0.002 Tc
+0.26 Tw
+[(constituency, s)22(o)-2( if pr)15(efer)-5(e)18(n)-2(ces ar)15(e also h)18(e)-2(ter)-5(o)-2(g)18(ene)18(ous, )-20(few )-20(p)18(eople )-20(will )-20(be)]TJ
+T*
+-0.001 Tw
+[(hi)5(ghl)5(y sati)5(sfi)5(ed by)23( the l)5(e)-1(v)23(e)-1(l)5( of pu)19(bl)5(i)5(c)3( good c)23(hosen.)]TJ
+0 -2.32 TD
+0.22 Tw
+[(A)9(s)2( )20(jur)-5(i)4(sdictions )20(beco)18(m)-5(e )20(ge)18(ogr)-5(a)18(phically sm)-5(aller)15(,)0( the)18( constitu)18(ency will tend t)20(o)]TJ
+0 -1.14 TD
+0.004 Tc
+0.418 Tw
+[(become )20(more)20( homo)20(gene)20(ous so th)20(at the )20(outcom)17(e)0( conve)20(r)-3(ges t)22(o)0(w)6(a)0(rd the)]TJ
+0 -1.16 TD
+0.003 Tc
+0.239 Tw
+[(i)5(n)-1(terests of)21( each i)5(n)19(di)5(vi)5(dual)5(. In)19( )-20(si)5(tuati)5(ons)23( )-20(w)5(here di)5(sti)5(n)-1(ct )-20(g)19(r)-4(oups )-20(h)19(a)-1(ve )-20(str)16(ong)]TJ
+T*
+0.079 Tw
+[(prefer)16(ences, i)5(t)1( )20(may m)16(a)-1(ke sens)23(e to desi)25(gn )-20(the )-20(j)25(u)-1(ri)5(sdi)5(c)3(ti)5(on arou)19(nd )-20(thi)5(s)3( )-20(g)19(r)-4(oup)19( )-20(to)]TJ
+T*
+0.3 Tw
+[(m)-5(i)4(nim)-5(i)4(se inte)18(r)-5(nal h)18(e)-2(ter)-5(o)18(geneity. )20(\()-5(O)0(lson, )20(1980)18(\))-5( F)-7(o)18(r)-5( )-20(exa)18(m)-5(ple, )-20(iwi )-20(coul)24(d )-20(be)]TJ
+T*
+0.199 Tw
+[(argued )20(to hav)23(e di)5(sti)5(n)-1(ct p)19(r)-4(efe)19(r)-4(ences f)21(o)-1(r r)16(e)-1(sourc)23(e)-1( )-20(man)19(agem)16(ent )-20(th)19(at )-20(sugg)19(ests)]TJ
+0 -1.14 TD
+0.08 Tw
+[(separ)-5(ate)18( )20(iwi )20(autho)18(r)-5(i)4(ties )20(on s)22(o)-2(m)-5(e)-2( issu)18(es. With local g)18(o)-2(ver)-5(n)18(m)-5(ent t)20(he con)18(nection)]TJ
+0 -1.16 TD
+0.359 Tw
+[(betw)5(een )20(r)16(a)-1(tes, )20(regul)5(ati)5(o)19(n and)19( servi)5(c)3(es i)5(s)3( t)21(r)-4(ansp)19(a)-1(rent)21(. If p)19(r)-4(efer)16(ences f)21(o)-1(r)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(regul)6(ati)6(o)0(n)20( and )20(publ)6(i)6(c)4( servi)6(c)24(es are v)24(e)0(ry h)20(e)0(terog)20(eneo)20(us )-20(am)17(ong )-20(l)6(o)0(cal)6( )-20(j)6(u)20(ri)6(sdi)6(c)4(ti)6(ons)]TJ
+T*
+0.001 Tc
+0.001 Tw
+[(a national )20(policy will be m)-6(u)-3(c)21(h)-3( less efficie)17(n)-3(t than)17( a m)14(u)-3(ltitude o)17(f)-1( local policies.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.119 Tw
+[(Many )20(deci)5(s)3(i)5(o)19(ns )20(al)5(so )20(i)5(n)-1(vol)5(v)3(e)19( )20(obj)5(ecti)5(ve f)21(a)-1(cts and)19( compl)25(e)-1(x proc)23(esses. In)19( these)]TJ
+0 -1.16 TD
+0.079 Tw
+[(cases, i)5(f)1( deci)5(s)3(i)5(ons )20(are )20(made w)5(i)5(t)21(hout acc)23(e)-1(ss to )-20(go)19(od )-20(obj)25(ecti)5(ve )-20(i)5(n)-1(fo)19(rmati)5(o)19(n)-1( )-20(and)]TJ
+T*
+0.02 Tw
+[(skills )20(for)-5( analysing)18( com)-5(p)-2(lex)22( pr)-5(ocess)22(e)-2(s, r)-5(e)-2(s)22(u)-2(lts m)-5(a)-2(y )20(be po)18(or)-5(. If)20( decision)18(-)-5(m)-5(a)-2(ke)18(r)-5(s)]TJ
+T*
+0.119 Tw
+[(real)5(i)5(s)3(e thei)25(r l)5(a)-1(ck of i)5(n)19(for)16(m)-4(ati)5(on, t)21(hey m)16(a)-1(y )-20(seek )-20(i)5(t)1( )-20(f)21(r)-4(om el)5(sew)5(her)16(e. )-20(F)14(r)-4(eque)19(ntl)5(y)3(,)]TJ
+T*
+0.159 Tw
+[(however)-4(, t)21(hey m)-4(a)-1(y)23( not b)19(e)-1( awar)16(e of th)19(e infor)16(m)-4(ation)19( and skills )-20(ne)19(eded,)21( )-20(or)-4( )-20(b)19(e)]TJ
+0 -1.14 TD
+0.039 Tw
+[(abl)5(e to con)19(t)1(ract f)21(o)-1(r i)5(t)1( ef)21(fecti)5(v)3(el)5(y. E)10(ffecti)5(v)23(e )-20(contr)16(a)-1(cti)5(ng )-20(f)21(o)-1(r )-20(advi)5(c)3(e)19( )-20(req)19(u)-1(i)5(r)-4(es )-20(so)19(me)]TJ
+0 -1.16 TD
+0.199 Tw
+[(under)-4(sta)19(nding )40(of )20(the )20(natur)16(e of a)19(d)-1(vice r)-4(e)19(quir)-4(ed,)21( and )20(an ability to)19( assess th)19(e)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(qual)6(i)6(t)2(y of i)6(n)0(fo)20(rmati)26(on rec)24(e)0(i)6(v)4(ed.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.199 Tw
+[(In refl)5(ecti)5(n)19(g)-1( al)5(l)5( the )20(rel)5(e)-1(va)19(nt i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)19(,)1( then,)21( i)5(t)1( i)5(s)3( i)5(m)-4(po)19(rtant )20(to consi)5(d)19(er )-20(th)19(e)]TJ
+0 -1.14 TD
+-0.001 Tc
+[(fo)-5(llo)-5(win)-5(g)-5(:)]TJ
+/F12 1 Tf
+0 -2.4 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.002 Tc
+0.18 Tw
+[(Wher)-5(e )20(is the)18( subjective in)18(for)-5(m)15(ation h)18(e)-2(ld? )20(T)-7(h)-2(is will r)-5(equi)24(r)-5(e)-2( de)18(ter)-5(m)-5(i)24(ning)]TJ
+0 -1.16 TD
+0 Tc
+0.002 Tw
+[(wh)-4(e)-4(r)-7(e)-4( th)-4(e)16( e)-4(ffe)-4(cts )20(a)-4(r)-7(e)-4( f)18(e)-4(lt, sin)-4(c)0(e)-4( it is t)18(h)-4(o)-4(s)0(e)-4( )-20(a)-4(f)18(fe)-4(cte)-4(d)-4( )-20(t)18(h)-4(a)-4(t)-2( )-20(will )-20(h)-4(a)-4(v)0(e)16( )-20(su)-4(b)-4(j)2(e)-4(c)0(tive)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(prefer)17(ences. A)11(r)17(e these pref)22(erenc)24(es )-20(rel)6(a)0(ti)6(v)24(e)0(l)6(y)4( )-20(hom)17(ogeno)20(us )-20(or )-20(e)20(x)4(tre)20(m)-3(el)6(y)]TJ
+0 -1.16 TD
+[(vari)6(ed?)]TJ
+/F12 1 Tf
+-2.36 -2.38 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(here i)5(s)3( the)19( obj)5(ecti)5(ve i)5(n)19(form)16(ati)5(on h)19(e)-1(l)5(d? H)5(o)-1(w)5( e)19(a)-1(si)5(l)5(y)3( can i)5(t)1( b)19(e)-1( tra)19(n)-1(sfer)16(red?)]TJ
+/F12 1 Tf
+-2.36 -2.4 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(hat i)5(s)3( the r)16(e)-1(l)5(a)-1(ti)5(ve i)5(m)-4(p)19(o)-1(rta)19(n)-1(ce of su)19(bj)5(ecti)5(ve an)19(d obj)5(ecti)5(v)23(e)-1( i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)19(?)]TJ
+-2.36 -2.3 TD
+0.019 Tw
+[(A)10(s)3( )20(a )20(general)5( )20(pri)5(n)-1(ci)5(pl)5(e,)21( deci)5(s)3(i)5(on )20(maki)5(ng sh)19(oul)5(d r)16(e)-1(st w)5(i)5(t)1(h th)19(e l)5(e)-1(vel)5( of )20(gover)16(nment)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(that can acc)23(e)-1(ss the )20(great)21(est am)16(ount o)19(f)1( rel)5(e)-1(v)23(ant i)5(n)-1(fo)19(rmati)5(o)19(n)-1(.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 146.72 Tm
+0.005 Tc
+-0.003 Tw
+[(B)7(a)1(lance)21(d)-4( d)16(ecisi)23(on m)14(aki)23(ng)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 120.56 Tm
+0.003 Tc
+0.019 Tw
+[(W)7(hen )20(publ)5(i)5(c)3( go)19(ods a)19(r)-4(e pr)16(ovi)5(ded o)19(u)-1(t of t)21(a)-1(x reve)19(nue, t)21(he conce)19(r)-4(n th)19(at thos)23(e w)5(h)-1(o)]TJ
+T*
+0.079 Tw
+[(are affec)23(t)1(ed by )20(a reg)19(u)-1(l)5(a)-1(ti)5(on )20(al)5(so cont)21(rol)5( i)5(t)1( i)5(s)3( exp)19(r)-4(essed as )-20(Fi)5(scal)5( )-20(E)10(qui)5(val)25(ence,)]TJ
+T*
+0.019 Tw
+[(\223a )20(matc)23(h )20(betw)5(e)-1(e)19(n)-1( )20(those)19( )20(w)5(ho r)16(e)-1(cei)5(v)3(e th)19(e benefi)25(t)1(s of a c)23(o)-1(l)5(l)5(e)-1(cti)5(v)3(e go)19(od and)19( those)]TJ
+ET
+endstream endobj 167 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 168 0 obj << /Type /Font /Subtype /Type1 /Name /F12 /BaseFont /Symbol >> endobj 169 0 obj << /Length 8287 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(18)Tj
+-34.32 58.88 TD
+0.158 Tw
+[(w)6(ho pay fo)20(r i)6(t)2(\224.)]TJ
+10.08 0 0 10.08 183.84 747.805 Tm
+0 Tc
+0 Tw
+(6)Tj
+12 0 0 12 189.36 744.8 Tm
+0.003 Tc
+0.179 Tw
+[( )20( D)5(e)-1(ci)5(si)5(ons can )20(be i)5(neffi)5(ci)5(e)19(n)-1(t w)5(hen )20(the costs)23( are )20(born)19(e)-1( by)]TJ
+-7.5 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(ei)6(ther a l)6(a)20(rge)20(r)-3( gro)20(up tha)20(n)0( rec)24(e)0(i)6(v)4(e the )20(benefi)6(t)2(s, )20(or a)20( smal)6(l)6(e)0(r)17( gro)20(up.)]TJ
+12 0 2.551 12 99.36 703.28 Tm
+0.002 Tc
+0 Tw
+[(W)6(i)4(thin Jurisdictions)]TJ
+12 0 0 12 99.36 677.36 Tm
+0.119 Tw
+[(One )20(speci)5(f)1(i)5(c)3( )20(pu)19(bl)5(i)5(c)3( choi)5(ce p)19(r)-4(obl)5(e)19(m)-4( i)5(n)-1( the)19( R)5(M)-4(A)10(,)1( i)5(s)3( that )20(the p)19(r)-4(i)5(m)-4(ary)23( meth)19(od of)]TJ
+T*
+0.479 Tw
+[(provi)5(s)3(i)5(on )20(of )20(publ)5(i)5(c)3( go)19(ods, an)19(d pr)16(eventi)5(on )20(of exte)19(rnal)5(i)5(t)1(i)5(e)-1(s, i)5(s)3( )20(regul)5(a)19(t)1(i)5(on.)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(P)11(u)0(rchase of t)22(he pu)20(bl)6(i)6(c)4( good i)6(s)4( )20(not ge)20(neral)6(l)6(y)4( )20(an opti)6(o)20(n. T)15(heref)22(ore )20(al)6(l)6( costs )-20(ar)17(e)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(borne by)23( l)5(and/)21(resou)19(r)-4(ce ow)5(ne)19(rs, not)21( shar)16(ed acr)16(o)-1(ss the j)5(u)19(ri)5(sdi)5(c)3(ti)5(on. )20( Thi)5(s)3( l)5(e)-1(a)19(d)-1(s )-20(to)]TJ
+0 -1.14 TD
+[(over-p)19(rovi)5(si)5(on )-20(i)5(n)-1( a )-20(dem)16(ocracy because)19( )-20(govern)19(m)-4(en)19(t )-20(\(tax)23(payers)23(\))-4( )-20(do )-20(n)19(o)-1(t )-20(bea)19(r )-20(the)]TJ
+0 -1.16 TD
+0.018 Tw
+[(costs of thei)25(r deci)5(s)3(i)5(ons )19(\(E)10(pstei)5(n)-1(, 1)19(995\))16(. A)10(fter t)21(he re)19(gul)5(ati)5(on )19(has be)19(en i)5(m)-4(p)19(o)-1(sed,)]TJ
+0 -1.26 TD
+0 Tw
+[(the land will be )20(used in )20(a const)20(r)-5(ained )20(efficient way.)]TJ
+10.08 0 0 10.08 368.88 595.885 Tm
+0 Tc
+(7)Tj
+12 0 0 12 99.36 565.28 Tm
+0.003 Tc
+0.259 Tw
+[(The pu)19(bl)5(i)5(c)3( choi)5(ce a)19(nd effi)5(ci)5(ency)23( pro)19(b)-1(l)5(e)-1(ms cr)16(eated )20(by unev)23(en )-20(cost beari)5(n)19(g)]TJ
+0 -1.16 TD
+0.119 Tw
+[(w)5(i)5(t)1(hi)5(n a j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( are )20(prob)19(abl)5(y l)5(e)-1(ssen)19(ed )-20(by )-20(d)19(e)-1(vol)5(u)-1(ti)5(on becaus)23(e )-20(the )-20(a)19(ffl)5(i)5(c)3(ted)]TJ
+T*
+0.319 Tw
+[(agent )20(i)5(s)3( \221)5(l)5(a)-1(r)16(ger\222)5(,)1( i)5(n)-1( )20(a pol)5(i)5(t)1(i)5(c)3(al)5( se)19(nse, i)5(n)-1( a)19( l)5(o)-1(cal)5( j)5(u)-1(ri)5(sdi)5(c)3(ti)25(on that)21( i)5(n)-1( cent)21(ral)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(govern)20(m)-3(ent. )20( B)11(e)0(ca)20(use ag)20(ents a)20(r)-3(e mo)20(re ho)20(moge)20(neous i)6(n)20( a smal)6(l)6(e)20(r j)6(u)0(ri)6(sdi)6(c)4(ti)26(on,)]TJ
+0 -1.14 TD
+-0.001 Tc
+0.083 Tw
+[(th)-5(o)-5(s)-1(e)-5( wh)-5(o)-5( a)15(r)-8(e)-5( fo)15(r)-8(c)-1(e)-5(d)-5( t)17(o)-5( p)-5(r)-8(o)-5(v)-1(i)21(d)-5(e)-5( th)-5(e)-5( )20(p)-5(u)-5(b)-5(lic g)-5(o)-5(o)15(d)-5( )-20(will )-20(b)-5(e)-5( )-20(a)-5( )-20(l)21(a)-5(r)-8(g)-5(e)15(r)-8( )-20(p)-5(e)15(r)-8(c)-1(e)-5(n)-5(t)-3(a)-5(g)15(e)-5( )-20(o)-5(f)]TJ
+0 -1.16 TD
+0.003 Tc
+0.039 Tw
+[(the )20(popul)25(ati)5(on on)19( each i)5(ssu)19(e. On t)21(he oth)19(e)-1(r han)19(d, i)5(n)-1( ce)19(ntral)5( )20(gover)16(nment,)21( si)5(mi)5(l)5(a)-1(r)]TJ
+T*
+0.2 Tw
+[(situations will occur)15( fr)-5(eq)18(uently so )20(ther)15(e m)-5(a)-2(y be)18( m)-5(o)18(r)-5(e)-2( )-20(p)18(r)-5(essur)15(e)-2( )-20(to )-20(hav)22(e )-20(fair)-5(,)]TJ
+T*
+0 Tw
+[(consi)4(s)2(tent deci)4(s)2(i)4(o)18(ns.)]TJ
+12 0 2.551 12 99.36 440.48 Tm
+0.004 Tc
+-0.002 Tw
+[(B)11(e)0(tw)6(een Juri)6(sdi)6(c)4(ti)6(o)20(n)0(s: Inte)20(rj)6(uri)6(s)4(di)6(cti)6(o)20(nal)6( E)11(x)4(tern)20(al)6(i)6(t)2(i)6(e)0(s)]TJ
+12 0 0 12 99.36 414.56 Tm
+-0.001 Tc
+0.263 Tw
+[(T)-10(h)-5(e)-5( )20(sa)15(m)-8(e)-5( )20(p)-5(u)-5(b)-5(lic )20(c)19(h)-5(o)-5(i)1(ce)-5( p)15(r)-8(o)-5(b)-5(l)1(e)-5(m)-8(s)19( th)-5(a)-5(t)-3( o)-5(c)-1(c)19(u)-5(r)-8( with)-5(i)1(n)-5( )20(a)-5( ju)-5(r)-8(i)1(sd)-5(ictio)15(n)-5( will o)-5(ccu)-5(r)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(betw)5(een j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons i)5(f)1( t)21(he costs a)19(nd be)19(nefi)5(t)1(s )-20(a)19(r)-4(e )-20(not)21( )-20(born)19(e)-1(/rec)23(ei)5(ved )-20(by )-20(t)21(h)-1(e)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(same peo)20(pl)6(e. A)11(n)0(y fo)20(rm of)22( devol)6(uti)6(o)20(n l)6(eads )-20(t)22(o)0( )-20(a )-20(l)6(i)6(m)-3(i)6(t)2(e)20(d)0( )-20(nu)20(mber of )-20(gove)20(r)-3(nm)17(ent)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(bodi)5(es, )20(eac)23(h )20(of )20(w)5(h)-1(i)5(c)3(h )20(deal)5(s w)5(i)5(t)1(h a)19( ran)19(ge of i)5(ssu)19(es and )20(a fi)5(xed g)19(eogr)16(aphi)5(cal)]TJ
+0 -1.14 TD
+0.004 Tc
+0.058 Tw
+[(area. I)22(n)0( N)6(e)0(w)6( Ze)20(al)6(and 7)20(4)0( ter)17(r)-3(i)6(t)2(ori)6(a)0(l)6( l)26(o)0(cal)6( aut)22(hori)6(t)2(i)6(e)0(s )20(and 12)20( regi)6(o)20(nal)6( )-20(aut)22(hori)6(t)2(i)6(e)0(s)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(cover res)23(ource)19( mana)19(geme)19(n)-1(t i)5(ssues i)5(n)-1( )20(thei)5(r j)5(u)-1(r)16(i)5(sdi)5(c)3(ti)5(ons. )-20(Thi)5(s)3( means )-20(t)21(hat )-20(fo)19(r)]TJ
+T*
+0.099 Tw
+[(al)5(most )20(eve)19(r)-4(y i)5(ndi)5(vi)5(dual)5( i)5(s)3(s)23(ue the)19(r)-4(e i)5(s)3( a )20(mi)5(smatc)23(h)-1( betw)5(e)-1(e)19(n)-1( the j)5(u)19(ri)5(sdi)5(c)3(ti)5(on )20(and)]TJ
+T*
+[(the )20(spati)5(a)-1(l)5( )20(di)5(st)21(ri)5(buti)5(o)19(n )20(of th)19(e effects.)21( W)7(hen t)21(he j)5(u)-1(ri)5(sdi)5(c)3(ti)25(on i)5(s)3( smal)5(l)5(e)19(r tha)19(n)-1( the)]TJ
+T*
+-0.001 Tw
+[(area aff)21(e)-1(cted )20(an i)5(n)-1(te)19(rj)5(uri)5(s)3(di)5(cti)5(o)-1(n)19(a)-1(l)5( exte)19(rnal)5(i)5(t)1(y i)5(s)3( cr)16(eated.)]TJ
+12 0 2.551 12 99.36 275.84 Tm
+[(S)10(ources of In)19(terj)5(u)19(r)-4(i)5(s)3(di)5(cti)5(onal)5( E)10(x)3(te)19(rnal)5(i)5(t)1(i)5(e)-1(s)]TJ
+12 0 0 12 99.36 249.92 Tm
+[(E)10(n)-1(vi)5(ronment)21(al)5( exter)16(nal)5(i)5(t)1(i)5(e)-1(s)]TJ
+ET
+1 i
+99.36 248.72 144 -0.72 re
+f*
+BT
+12 0 0 12 99.36 222.08 Tm
+0.004 Tc
+0.118 Tw
+[(The )20(m)17(o)0(st obvi)6(ous)24( exter)17(nal)6(i)6(t)2(y i)6(s)4( w)6(h)0(e)20(r)-3(e an )20(envi)6(r)-3(on)20(ment)22(al)6( benefi)6(t)22( or h)20(a)0(rm )20(goes)]TJ
+0 -1.14 TD
+0.003 Tc
+0.099 Tw
+[(beyond th)19(e j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1(. E)10(.)1(g.: n)19(a)-1(ti)5(on-w)5(i)5(d)19(e bene)19(fi)5(ts fro)19(m)-4( bi)5(odi)5(ve)19(rsi)5(t)1(y )-20(p)19(r)-4(otecti)5(on)19(.)]TJ
+0 -1.84 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+200.166 190.4 m
+99.366 190.4 l
+S
+BT
+12 0 0 12 200.16 186.32 Tm
+( )Tj
+ET
+243.843 190.4 m
+200.163 190.4 l
+S
+BT
+10.08 0 0 10.08 99.36 174.685 Tm
+0 Tc
+(6)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.016 Tw
+[( )-1976(O)-16(l)0(s)-8(on,)-16( 1980 p.)-16( 30)]TJ
+-0.5476 -2.2857 TD
+0 Tc
+0 Tw
+(7)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.373 Tw
+[( )-1619(Howev)-8(er)-8(,)-16( unc)-8(er)-8(t)-16(aint)-16(y)-8( about)-16( )24(t)-16(he pos)-8(s)-8(ibilit)-16(y)-8( of)-16( )24(f)-16(u)0(t)-16(u)0(r)-8(e)0( )28(t)-16(a)0(k)-8(ings)-8( c)-8(an lead t)-16(o)0( )24(s)-8(ignif)-16(ic)-8(ant)]TJ
+2.2619 -1.1667 TD
+0.086 Tw
+[(dis)-8(t)-16(o)0(r)-8(t)-16(ions)-8( in behav)-8(iour)-8(.)-16( F)-16(o)0(r)15( ex)-8(am)-8(ple,)-16( a)24( landowner)-8( who dis)-8(c)-8(o)0(v)-8(e)0(r)-8(s)-8( a lar)-8(ge s)-8(t)-16(and of)8( r)-8(i)0(m)-8(u)]TJ
+0 -1.1429 TD
+0.04 Tw
+[(on his)-8( pr)-8(oper)-8(t)-16(y)-8( would not)-16( want)-16( )24(t)-16(o)0( not)-16(if)8(y)-8( t)-16(he gov)-8(er)-8(nm)-8(en)24(t)-16(,)-16( bec)-8(aus)-8(e he m)-8(a)0(y)-8( )-23(be )-23(c)-8(ons)16(t)-16(r)-8(ained)]TJ
+0 -1.1667 TD
+0.206 Tw
+[(f)-16(r)-8(om)-8( )24(f)-16(elling it)-16(.)-16( )24(I)-16(f)-16( he )24(t)-16(hink)-8(s)-8( gov)-8(er)-8(nm)-8(ent)8( will dis)-8(c)-8(o)0(v)-8(e)0(r)-8( it)-16(,)-16( he)24( )-24(will )-24(f)-16(ell )-24(it)-16( )-24(quic)-8(k)-8(l)0(y)-8( )-24(bef)-16(or)-8(e )-24(a)]TJ
+0 -1.1429 TD
+0.254 Tw
+[(r)-8(egulat)-16(ion )24(c)-8(an )24(be im)-8(pos)-8(ed,)-16( ev)-8(en if)-16( he would not)-16( hav)-8(e c)-8(hos)-8(en )24(t)-16(o)0( in t)-16(h)0(e)24( abs)-8(enc)-8(e of)]TJ
+T*
+[(r)-8(egulat)-16(ion.)]TJ
+ET
+endstream endobj 170 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 171 0 obj << /Length 7936 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(19)Tj
+-34.32 58.98 TD
+0.002 Tc
+0 Tw
+[(Decision-)-5(m)-5(a)-2(ke)18(r)-5(s)2( will tend )20(to und)18(er)-5(-)-5(s)22(upply th)18(e )-20(envir)15(onm)-5(en)18(tal )-20(ben)18(efit )-20(beca)18(u)-2(se )-20(all)]TJ
+0 -1.16 TD
+0.099 Tw
+[(the costs a)19(r)-4(e bo)19(rne i)5(n)-1(si)5(d)19(e)-1( the )-20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(on, but )-20(onl)5(y the )-20(f)21(r)-4(acti)5(on )-20(o)19(f)1( )-20(the )-20(b)19(enefi)5(t)1(s)]TJ
+T*
+-0.001 Tc
+0.063 Tw
+[(r)-8(e)-5(ce)-5(ive)-5(d)-5( )20(with)-5(i)1(n)15( )20(th)-5(e)-5( )20(ju)15(r)-8(i)1(sd)-5(ictio)-5(n)-5( )20(will b)-5(e)-5( t)17(a)-5(ke)-5(n)-5( in)-5(to)15( a)-5(cco)-5(u)15(n)-5(t. T)10(h)-5(e)-5( d)-5(e)-5(c)-1(isio)15(n)-5(-)-8(m)-8(a)-5(k)19(e)-5(r)-8(s)]TJ
+T*
+0.002 Tc
+0.12 Tw
+[(will allow over)-5(-)-5(p)18(r)-5(oductio)18(n)-2( of p)18(o)-2(lluting activities,)20( )-20(becaus)22(e )-20(the benefits fr)-5(om)15( )-20(the)]TJ
+0 -1.14 TD
+0.339 Tw
+[(pol)5(l)5(u)-1(ti)5(ng )20(acti)5(vi)5(ty )20(a)19(r)-4(e )20(co)19(ntai)5(ned )20(i)25(n)-1(si)5(de )20(w)5(h)-1(i)5(l)5(e)-1( som)16(e)-1( of)21( the h)19(a)-1(rm i)5(s)3( s)23(u)-1(ffer)16(e)-1(d)]TJ
+0 -1.16 TD
+[(outsi)5(de.)]TJ
+0 -2.32 TD
+0 Tc
+0.002 Tw
+[(Ne)-4(two)-4(r)-7(k e)-4(x)0(te)16(m)-7(a)-4(litie)-4(s)]TJ
+ET
+1 i
+99.36 647.6 110.64 -0.72 re
+f*
+BT
+12 0 0 12 99.36 621.2 Tm
+0.003 Tc
+0.039 Tw
+[(A)10( )20(netw)5(o)-1(rk exte)19(rnal)5(i)5(t)1(y a)19(r)-4(i)5(s)3(es w)5(hen)19( addi)5(ng)19( anoth)19(e)-1(r a)19(gent to)19( the n)19(e)-1(tw)5(ork n)19(o)-1(t onl)5(y)]TJ
+0 -1.16 TD
+0.079 Tw
+[(provi)5(des )20(se)19(rvi)5(c)3(e to t)21(he ag)19(ent ad)19(ded b)19(u)-1(t al)5(so i)5(m)16(proves)23( servi)5(c)3(es t)21(o)-1( al)5(l)5( oth)19(e)-1(rs i)5(n)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(the netw)6(o)20(rk. F)15(o)0(r exa)20(m)-3(pl)6(e, )20(provi)6(d)0(i)6(n)0(g)20( tel)6(eph)20(one se)20(rvi)6(c)4(e to anothe)20(r )-20(com)17(m)-3(uni)6(ty)]TJ
+T*
+0.003 Tc
+0.519 Tw
+[(hel)5(ps )20(those i)25(n)-1( that c)23(o)-1(mm)16(uni)5(ty and)19( al)5(so be)19(nefi)5(t)1(s oth)19(e)-1(rs w)5(h)-1(o)19( w)5(ant to)]TJ
+T*
+0.079 Tw
+[(communi)5(ca)19(te )20(w)5(i)5(t)1(h th)19(em. E)10(x)3(ten)19(d)-1(i)5(ng a )20(netw)5(o)-1(rk )20(may al)5(so)19( l)5(o)-1(w)5(e)-1(r th)19(e costs o)19(f)1( the)]TJ
+0 -1.14 TD
+0.139 Tw
+[(next extensi)5(o)19(n. If l)5(i)5(n)-1(ki)5(n)19(g)-1( deci)5(s)3(i)5(ons )20(are al)5(l)5( )-20(made )-20(s)23(epar)16(atel)5(y )-20(they)23( )-20(may )-20(n)19(o)-1(t )-20(be)]TJ
+0 -1.16 TD
+0.279 Tw
+[(i)5(ndi)5(vi)5(dual)5(l)5(y)3( rati)5(o)19(nal)5( even)19( i)5(f)1( they w)5(o)19(ul)5(d be j)5(o)-1(i)25(n)-1(tl)5(y effi)5(ci)5(ent.)21( If so)19(me age)19(nts)]TJ
+T*
+0.179 Tw
+[(provi)5(de )20(si)5(gni)25(fi)5(cant )20(ne)19(tw)5(ork )20(ext)21(e)-1(rnal)5(i)5(t)1(i)5(e)-1(s)23( )20(becaus)23(e )20(of cri)5(t)1(i)5(c)23(al)5( l)5(o)-1(cati)5(on )20(or si)5(ze o)19(f)]TJ
+T*
+0.059 Tw
+[(popul)5(ati)5(on i)5(t)21( may b)19(e)-1( w)5(o)-1(rt)21(h subsi)5(d)-1(i)5(s)3(i)5(ng )20(thei)5(r c)23(onnecti)5(o)19(n)-1(. )-20( )-20(C)5(onve)19(r)-4(sel)5(y)3(, )-20(th)19(ey )-20(may)]TJ
+T*
+0.459 Tw
+[(w)5(ant to expl)5(oi)5(t)21( thei)5(r )20(posi)5(t)1(i)5(on o)19(f)1( stre)19(ngth to)19( extrac)23(t the val)25(ue of t)21(hose)]TJ
+0 -1.14 TD
+0.239 Tw
+[(external)5(i)5(t)1(i)5(e)-1(s.)21( )20( )20(The)19( )20(trans)23(acti)5(on costs)23( of coo)19(r)-4(di)5(nati)5(n)19(g a n)19(e)-1(tw)5(ork )20(may be )20(hi)5(gh)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(enough t)21(o)-1( j)5(u)-1(sti)5(f)1(y cen)19(t)1(ral)5( co)19(ntrol)5( o)19(n)-1( netw)5(o)19(rk i)5(ssues.)]TJ
+0 -2.32 TD
+[(P)10(e)-1(cuni)5(ary exte)19(rnal)5(i)5(t)1(i)5(e)-1(s)]TJ
+ET
+99.36 439.52 120.72 -0.72 re
+f*
+BT
+12 0 0 12 99.36 413.12 Tm
+0.119 Tw
+[(A)10( )20(deci)5(s)3(i)5(on )20(w)5(i)5(t)1(hi)5(n )20(a )20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(on )20(m)16(a)-1(y rest)21(ri)5(ct reso)19(urce)19( use i)5(n)-1( suc)23(h)-1( a w)5(a)-1(y t)21(hat i)5(t)]TJ
+0 -1.16 TD
+0.004 Tc
+0.158 Tw
+[(di)6(mi)6(ni)6(shes )20(th)20(e )20(oppo)20(rtuni)6(ti)6(es)24( )20(for ca)20(pi)6(tal)6( an)20(d l)6(abou)20(r l)6(ooki)6(n)0(g)20( to mi)6(g)20(r)-3(ate i)6(n)20(to the)]TJ
+T*
+0.003 Tc
+0.379 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on. It)21( i)5(s)3( someti)25(mes a)19(r)-4(gued )20(that st)21(rong )20(regul)5(a)19(t)1(i)5(on di)5(sadv)23(antag)19(es)]TJ
+T*
+0.459 Tw
+[(busi)5(nesses th)19(at w)5(i)5(s)3(h to l)5(o)-1(c)23(a)-1(te i)5(n)-1( a)19(n)-1( ar)16(ea, an)19(d ther)16(efor)16(e i)5(t)1( shoul)25(d be)]TJ
+T*
+[(constrai)5(ne)19(d.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.078 Tw
+[(There)20( are )20(extern)20(al)6(i)6(t)2(i)6(e)0(s fro)20(m)-3( the)20( deci)6(s)4(i)6(on b)20(u)0(t they are \223pecu)20(n)0(i)6(a)0(ry )-20(ext)22(e)0(rnal)6(i)6(t)2(i)6(e)0(s)24(\224)-3(.)]TJ
+0 -1.16 TD
+0.002 Tc
+0.02 Tw
+[(P)9(e)-2(cuniar)-5(y )20(exte)18(r)-5(nalities )20(a)18(r)-5(e sim)15(p)-2(ly the o)18(per)-5(ati)24(on of t)20(he pr)-5(ic)22(e system)-5(;)20( they a)18(r)-5(e an)]TJ
+T*
+0.039 Tw
+[(effi)5(ci)5(ent pa)19(rt of t)21(he ma)19(rket\222)5(s)3( r)16(e)-1(sponse)19( to sca)19(rci)5(t)1(y. A)10(ssumi)5(ng )20(ther)16(e are)19( no ot)21(her)]TJ
+T*
+0.004 Tc
+0.398 Tw
+[(i)6(n)0(terj)6(uri)6(s)4(di)6(cti)6(o)20(nal)6( exte)20(rnal)6(i)6(t)2(i)6(e)0(s, )20(and th)20(e publ)6(i)6(c)4( )-20(ch)20(oi)6(ce )-20(mec)24(hani)6(sm oper)17(ates)]TJ
+0 -1.14 TD
+0.003 Tc
+0.099 Tw
+[(effecti)5(v)3(el)5(y, thes)23(e deci)5(s)3(i)5(ons)23( are )20(di)5(sappoi)5(n)19(t)1(i)5(ng fo)19(r age)19(nts w)5(ho w)5(oul)25(d l)5(i)5(k)3(e )-20(to )-20(us)23(e)]TJ
+0 -1.16 TD
+0.139 Tw
+[(the reso)19(urces, )20(but not)21( i)5(neffi)5(ci)5(ent)21(. If pe)19(opl)5(e w)5(i)5(s)3(h to)19( constr)16(ai)5(n the)19( use of )20(thei)5(r)]TJ
+T*
+0.019 Tw
+[(ow)5(n resou)19(r)-4(ces th)19(ey shoul)5(d)19( be al)5(l)5(o)-1(w)5(e)19(d )-20(to. The )-20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(on )-20(i)5(s)3( )-20(d)19(e)-1(ci)5(di)5(ng )-20(to use )-20(th)19(e)]TJ
+T*
+[(scarce )20(res)23(ources)23( for co)19(nserva)19(ti)5(on o)19(r)-4( l)5(o)-1(cal)5( pu)19(bl)5(i)5(c)3( goods )20(rathe)19(r)-4( tha)19(n)-1( gai)5(ni)5(n)19(g)-1( thei)5(r)]TJ
+T*
+0.006 Tc
+-0.004 Tw
+[(c)6(o)2(mmerc)6(i)28(a)2(l)8( v)6(a)2(l)8(ue.)]TJ
+0 -2.34 TD
+0.003 Tc
+0.139 Tw
+[(Thi)5(s)3( )20(needs)23( )20(to )20(be)19( )20(di)5(sti)5(ngui)5(sh)19(ed how)5(ev)23(er f)21(r)-4(om th)19(e use )20(of the R)25(M)-4(A)10( by exi)5(s)3(ti)5(ng)]TJ
+0 -1.16 TD
+0.06 Tw
+[(businesses to )20(pr)-5(eve)18(n)-2(t ent)20(r)-5(y)2( by co)18(m)-5(petito)18(r)-5(s on t)20(he g)18(r)-5(ound that )-20(th)18(e )-20(ent)20(r)-5(ants )-20(will)]TJ
+0 -1.14 TD
+[(l)5(o)-1(w)5(e)-1(r )20(the )20(p)19(r)-4(ofi)5(t)1(s )20(o)19(f)1( )20(exi)5(s)3(ti)5(ng )40(busi)5(nesses. )40( )20(The)19( adver)16(se effec)23(t)1(s of th)19(e ent)21(rants o)19(n)]TJ
+0 -1.16 TD
+0.279 Tw
+[(the l)5(o)-1(cal)5( busi)5(n)19(esses i)5(s)3( m)16(e)-1(rel)5(y)3( th)19(e ope)19(rati)5(on )20(of the )20(mark)23(et, thes)23(e adve)19(r)-4(se)]TJ
+T*
+0 Tc
+0.362 Tw
+[(e)-4(ffe)-4(cts )20(will )20(b)-4(e)-4( o)-4(ffs)20(e)-4(t)-2( b)-4(y)0( g)16(a)-4(in)-4(s to)-4( lo)-4(c)20(a)-4(l co)-4(n)-4(s)0(u)16(m)-7(e)-4(r)-7(s a)16(n)-4(d)-4( wo)-4(r)-7(k)20(e)-4(r)-7(s. Use)-4( )20(o)-4(f)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(regul)5(ati)5(o)-1(n)19( to p)19(r)-4(event )20(entry )20(occurs o)19(n)-1(l)5(y)3( because)19( of f)21(a)-1(i)5(l)5(u)-1(res i)5(n)-1( t)21(he l)5(o)-1(cal)5( s)23(o)-1(ci)5(al)]TJ
+T*
+0.004 Tc
+0.338 Tw
+[(choi)6(ce mech)20(ani)6(sm. )20(The)20(r)-3(e i)6(s)4( no rol)6(e)0( )-20(f)22(o)0(r )-20(gov)24(ernm)17(ent )-20(i)6(n)0(t)22(e)0(rventi)6(o)20(n )-20(on )-20(t)22(h)0(e)]TJ
+0 -1.14 TD
+0.003 Tc
+0.219 Tw
+[(grounds )40(of )20(pec)23(uni)5(ary )20(ex)23(tern)19(al)5(i)5(t)1(i)5(e)-1(s. H)5(o)-1(w)5(e)-1(ve)19(r, i)5(f)1( r)16(egul)5(ati)5(o)-1(n)19( to ad)19(dress p)19(ubl)5(i)5(c)]TJ
+ET
+endstream endobj 172 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 173 0 obj << /Type /Page /Parent 176 0 R /Resources 175 0 R /Contents 174 0 R >> endobj 174 0 obj << /Length 11548 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(20)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.239 Tw
+[(goods pr)16(obl)5(ems c)23(r)-4(eat)21(es a pec)23(uni)5(ary )20(extern)19(al)5(i)5(t)1(y as a si)5(d)19(e)-1( )-20(effect thi)5(s)3( )-20(i)5(s)3( )-20(not)]TJ
+0 -1.16 TD
+[(i)4(neffi)4(ci)4(ent.)]TJ
+0 -2.32 TD
+0.139 Tw
+[(Other, )20(more s)23(ubtl)5(e)-1( i)5(n)-1(st)21(ances of )20(exter)16(nal)5(i)5(t)1(i)5(e)-1(s betw)5(e)19(en j)5(u)-1(ri)5(s)23(d)-1(i)5(c)3(ti)5(ons )-20(i)5(n)-1(cl)5(ud)19(e )-20(tax)]TJ
+0 -1.14 TD
+0.004 Tc
+0.398 Tw
+[(external)6(i)6(t)2(i)6(e)0(s,)22( del)6(ete)20(r)-3(i)6(ous i)6(n)0(t)22(e)0(rj)6(uri)6(s)4(di)6(cti)26(onal)6( com)17(peti)6(t)2(i)6(on )20(and th)20(e \223n)20(ot )-20(i)6(n)0( )-20(my)]TJ
+0 -1.16 TD
+0.003 Tc
+0.219 Tw
+[(backyard)19(\224 )20(or )20(NI)21(MB)10(Y)10( )20(phenom)16(enon. )20( T)-6(hes)23(e ar)16(e discussed i)25(n)-1( A)10(ppendix )20(F)-6(o)-1(u)19(r)-4(:)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(Other )20(E)11(x)4(ter)17(nal)6(i)6(t)2(i)6(e)0(s. R)6(i)6(sk sha)20(r)-3(i)6(ng i)6(s)4( a)20(nothe)20(r for)17(m)-3( of c)24(o)0(st bea)20(ri)6(ng. )20(The )20(opti)6(m)-3(al)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(al)5(l)5(o)-1(cati)5(on of )20(ri)5(sk i)5(n)-1( re)19(gul)5(ati)5(o)-1(n)19( i)5(s)3( di)5(scussed i)5(n)19( A)10(ppendi)5(x S)10(i)5(x: R)5(i)5(sk B)10(eari)25(ng.)]TJ
+0 -2.3 TD
+0.159 Tw
+[(B)10(a)-1(l)5(anced effi)5(ci)5(ent)21( deci)5(s)3(i)5(ons occ)23(u)-1(r w)5(h)-1(e)19(n)-1( deci)5(s)3(i)5(ons,)21( costs an)19(d ben)19(efi)5(t)1(s )-20(ar)16(e )-20(al)5(l)]TJ
+0 -1.16 TD
+0.079 Tw
+[(l)5(o)-1(cated i)5(n)-1( th)19(e sam)16(e)-1( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1(. W)7(hen )20(benefi)5(t)1(s )20(and d)19(e)-1(ci)5(si)5(on )-20(maki)25(ng )-20(have)19( )-20(the)]TJ
+T*
+0.004 Tc
+0.338 Tw
+[(same )20(j)6(u)0(ri)6(sdi)6(c)4(ti)26(on )20(but )20(thi)6(s)4( j)6(u)0(ri)6(sdi)6(c)4(ti)6(o)20(n)0( i)6(s)4( mi)6(sm)17(atched w)6(i)6(t)22(h the cos)24(t)2( bea)20(ri)6(ng)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on, fi)5(scal)5( )20(extern)19(al)5(i)5(t)1(i)5(e)-1(s occur)16(;)1( w)5(hen )20(deci)5(s)3(i)5(on m)16(a)-1(ki)5(ng an)19(d )-20(cost )-20(b)19(eari)5(n)-1(g)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(have )20(the )20(s)24(a)0(me )20(j)6(u)20(ri)6(sdi)6(c)4(ti)6(on b)20(u)0(t thi)6(s)4( j)6(u)20(ri)6(sdi)6(c)4(ti)6(on i)6(s)4( mi)6(s)24(m)-3(atche)20(d)0( w)6(i)6(t)2(h th)20(e bene)20(fi)6(t)]TJ
+0 -1.14 TD
+0.003 Tc
+0.119 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on, )20(e)19(n)-1(vi)5(ron)19(m)-4(ental)5( )20(ex)23(tern)19(al)5(i)5(t)1(i)5(e)-1(s )20(occur)16(.)1( E)10(x)3(ternal)5(i)5(t)1(i)5(e)-1(s)23( of ei)5(th)19(er typ)19(e)-1( l)5(ead)]TJ
+0 -1.16 TD
+0.019 Tw
+[(to )20(unbal)5(a)19(n)-1(ced deci)5(s)3(i)5(o)19(ns. M)16(a)-1(tchi)5(ng t)21(he l)5(e)-1(vel)5( of)21( deci)5(s)3(i)5(ons t)21(o)-1( the l)25(e)-1(vel)5( of b)19(enefi)5(t)1(s)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(al)6(l)6(o)0(w)6(s)4( appro)20(p)0(ri)6(ate )20(di)6(versi)6(t)2(y i)6(n)0( pol)6(i)6(c)4(i)6(e)0(s; )-20(i)6(t)2( )-20(p)20(e)0(rmi)6(ts heter)17(ogene)20(ous )-20(l)6(o)0(cal)6( )-20(p)20(o)0(l)6(i)6(c)4(i)6(e)0(s)]TJ
+T*
+0.338 Tw
+[(w)6(here ap)20(pl)6(i)6(c)4(abl)6(e an)20(d avoi)6(ds t)22(hem w)6(h)20(ere t)22(hey ar)17(e i)6(nap)20(prop)20(ri)6(ate. )20(Tabl)6(e 1)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(summari)5(s)23(e)-1(s the )20(effects of)21( mi)5(smatc)23(hes.)]TJ
+/F3 1 Tf
+0 -2.82 TD
+0.006 Tc
+-0.004 Tw
+[(Table)22( 1 S)13(o)-3(ci)24(al C)8(h)17(oice a)22(nd D)28(evol)24(u)-3(ti)24(on)]TJ
+/F5 1 Tf
+0 -1.76 TD
+0.002 Tc
+0 Tw
+[(Local)4( D)4(e)-2(ci)4(si)4(ons)]TJ
+ET
+1 i
+99.36 440 84 -0.72 re
+f*
+BT
+/F3 1 Tf
+12 0 0 12 317.28 441.2 Tm
+0.007 Tc
+[(B)9(e)3(nefi)25(ts)]TJ
+ET
+93.36 453.2 0.72 -0.72 re
+f*
+93.36 453.2 0.72 -0.72 re
+f*
+94.08 453.2 108.48 -0.72 re
+f*
+202.56 453.2 0.72 -0.72 re
+f*
+203.28 453.2 108.24 -0.72 re
+f*
+311.52 453.2 0.72 -0.72 re
+f*
+312.24 453.2 108.24 -0.72 re
+f*
+420.48 453.2 0.72 -0.72 re
+f*
+421.2 453.2 124.32 -0.72 re
+f*
+545.52 453.2 0.72 -0.72 re
+f*
+545.52 453.2 0.72 -0.72 re
+f*
+93.36 452.48 0.72 -14.4 re
+f*
+545.52 452.48 0.72 -14.4 re
+f*
+BT
+/F5 1 Tf
+12 0 2.551 12 317.28 427.04 Tm
+0.003 Tc
+[(Local)-6695(N)5(a)-1(ti)5(onal)]TJ
+ET
+93.36 438.08 0.72 -13.92 re
+f*
+545.52 438.08 0.72 -13.92 re
+f*
+BT
+/F3 1 Tf
+12 0 0 12 99.36 412.88 Tm
+[( Co)13(sts)]TJ
+/F5 1 Tf
+12 0 2.551 12 208.32 413.12 Tm
+[(Local )20( )20(1)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 424.4 108.96 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 412.16 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.003 Tc
+[(B)10(a)-1(l)5(anced)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 409.52 108.96 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 397.52 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.001 Tc
+[(E)8(fficiently)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 394.88 108.96 -13.92 re
+f*
+BT
+12 0 0 12 331.44 383.6 Tm
+0 0 0 rg
+0.002 Tc
+[(diver)-5(s)2(e)]TJ
+ET
+0.898 0.898 0.898 rg
+420.48 424.4 125.04 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 412.16 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.005 Tc
+[(U)7(nder-p)21(rov)5(i)7(s)5(i)7(on)]TJ
+ET
+0.898 0.898 0.898 rg
+420.48 409.52 125.04 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 397.52 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.002 Tc
+[(Ineffi)4(ci)4(entl)4(y)]TJ
+ET
+0.898 0.898 0.898 rg
+420.48 394.88 125.04 -13.92 re
+f*
+BT
+12 0 0 12 440.64 383.6 Tm
+0 0 0 rg
+[(diver)-5(s)2(e)]TJ
+ET
+93.36 424.4 0.72 -43.44 re
+f*
+545.52 424.4 0.72 -43.44 re
+f*
+BT
+10.08 0 0 10.08 99.36 369.325 Tm
+10.532 Tc
+( )Tj
+12 0 2.551 12 208.32 369.68 Tm
+0.002 Tc
+[(N)4(a)-2(ti)4(onal)4( )20( 2)]TJ
+ET
+0.498 0.498 0.498 rg
+311.52 380.96 108.96 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 368.72 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.005 Tc
+[(Ov)5(er-p)21(rov)5(i)7(s)5(i)7(on)]TJ
+ET
+0.498 0.498 0.498 rg
+311.52 366.08 108.96 -28.56 re
+f*
+0.698 0.698 0.698 rg
+420.48 380.96 125.04 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 368.72 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.003 Tc
+[(B)10(a)-1(l)5(anced)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 366.08 125.04 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 354.08 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.002 Tc
+[(Ineffi)4(ci)4(entl)4(y)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 351.44 125.04 -13.92 re
+f*
+BT
+12 0 0 12 440.64 340.16 Tm
+0 0 0 rg
+[(diver)-5(s)2(e)]TJ
+ET
+93.36 380.96 0.72 -43.44 re
+f*
+545.52 380.96 0.72 -43.44 re
+f*
+BT
+10.08 0 0 10.08 99.36 325.885 Tm
+0 Tc
+( )Tj
+12 0 0 12 99.36 326.24 Tm
+0.003 Tc
+[(N)5(a)-1(ti)5(onal)]TJ
+ET
+99.36 325.04 43.92 -0.72 re
+f*
+BT
+12 0 0 12 99.36 312.32 Tm
+0.001 Tc
+(Decisions)Tj
+ET
+99.36 311.12 51.84 -0.72 re
+f*
+BT
+10.08 0 0 10.08 208.32 325.885 Tm
+10.532 Tc
+[( )-23( )]TJ
+ET
+93.36 337.52 0.72 -27.84 re
+f*
+545.52 337.52 0.72 -27.84 re
+f*
+BT
+10.08 0 0 10.08 99.36 298.045 Tm
+0 Tc
+( )Tj
+/F3 1 Tf
+12 0 0 12 99.36 298.4 Tm
+0.002 Tc
+[( Co)13(sts)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 208.32 298.285 Tm
+0 Tc
+( )Tj
+12 0 2.551 12 208.32 298.64 Tm
+0.002 Tc
+[(Local )20( )20(3)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 309.68 108.96 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 297.68 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.003 Tc
+[(B)10(a)-1(l)5(anced)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 295.04 108.96 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 282.8 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.002 Tc
+[(Ineffi)4(ci)4(entl)4(y)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 280.16 108.96 -13.68 re
+f*
+BT
+12 0 0 12 331.44 269.12 Tm
+0 0 0 rg
+[(consi)5(s)3(tent)]TJ
+ET
+0.698 0.698 0.698 rg
+311.52 266.48 108.96 -0.24 re
+f*
+0.498 0.498 0.498 rg
+420.48 309.68 125.04 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 297.68 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.005 Tc
+[(Ov)5(er-p)21(rov)5(i)7(s)5(i)7(on)]TJ
+ET
+0.498 0.498 0.498 rg
+420.48 295.04 125.04 -13.92 re
+f*
+BT
+10.08 0 0 10.08 426.48 283.405 Tm
+0 0 0 rg
+0 Tc
+( )Tj
+ET
+0.498 0.498 0.498 rg
+420.48 281.12 125.04 -14.88 re
+f*
+0 0 0 rg
+93.36 309.68 0.72 -43.44 re
+f*
+545.52 309.68 0.72 -43.44 re
+f*
+BT
+10.08 0 0 10.08 99.36 254.845 Tm
+10.532 Tc
+( )Tj
+12 0 2.551 12 208.32 255.2 Tm
+0.002 Tc
+[(N)4(a)-2(ti)4(onal)4( )20( 4)]TJ
+ET
+0.898 0.898 0.898 rg
+311.52 266.48 108.96 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 254.24 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.005 Tc
+[(U)7(nder-)]TJ
+ET
+0.898 0.898 0.898 rg
+311.52 251.6 108.96 -13.92 re
+f*
+BT
+12 0 0 12 331.44 240.32 Tm
+0 0 0 rg
+0.004 Tc
+[(provi)6(s)4(i)6(o)0(n)]TJ
+ET
+0.898 0.898 0.898 rg
+311.52 237.68 108.96 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 317.28 225.68 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.002 Tc
+[(Ineffi)4(ci)4(entl)4(y)]TJ
+ET
+0.898 0.898 0.898 rg
+311.52 223.04 108.96 -13.92 re
+f*
+BT
+12 0 0 12 331.44 211.76 Tm
+0 0 0 rg
+[(consi)5(s)3(tent)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 266.48 125.04 -14.88 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 254.24 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.003 Tc
+[(B)10(a)-1(l)5(anced)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 251.6 125.04 -14.64 re
+f*
+BT
+/F12 1 Tf
+12 0 0 12 426.48 239.6 Tm
+0 0 0 rg
+0 Tc
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+0.72 0.02 TD
+0.001 Tc
+[(E)8(fficiently)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 236.96 125.04 -13.92 re
+f*
+BT
+12 0 0 12 440.64 225.68 Tm
+0 0 0 rg
+0.003 Tc
+[(consi)5(s)3(tent)]TJ
+ET
+0.698 0.698 0.698 rg
+420.48 223.04 125.04 -13.92 re
+f*
+0 0 0 rg
+93.36 266.48 0.72 -57.36 re
+f*
+93.36 209.12 0.72 -0.72 re
+f*
+93.36 209.12 0.72 -0.72 re
+f*
+94.08 209.12 108.48 -0.72 re
+f*
+202.56 209.12 0.72 -0.72 re
+f*
+203.28 209.12 108.24 -0.72 re
+f*
+311.52 209.12 0.72 -0.72 re
+f*
+312.24 209.12 108.24 -0.72 re
+f*
+420.48 209.12 0.72 -0.72 re
+f*
+421.2 209.12 124.32 -0.72 re
+f*
+545.52 266.48 0.72 -57.36 re
+f*
+545.52 209.12 0.72 -0.72 re
+f*
+545.52 209.12 0.72 -0.72 re
+f*
+BT
+12 0 2.551 12 99.36 183.44 Tm
+[(Local)4( D)4(e)-2(ci)4(si)4(on M)15(a)-2(ki)4(ng)]TJ
+12 0 0 12 99.36 155.84 Tm
+0.159 Tw
+[(If the be)19(nefi)5(t)1(s a)19(r)-4(e rec)23(e)-1(i)5(v)3(ed by )20(a l)5(a)-1(rge)19(r)-4( g)19(r)-4(oup )-20(th)19(an )-20(th)19(e )-20(deci)5(s)3(i)5(on make)19(rs, )-20(and)]TJ
+0 -1.16 TD
+0.22 Tw
+[(costs ar)-5(e b)18(o)-2(r)-5(n)-2(e)18( by the )20(decision-)15(m)-5(a)-2(king )20(gr)-5(ou)18(p, public )20(goods will te)18(nd to b)18(e)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(under)17(-provi)6(d)20(ed \()17(r)-3(ow)6( one)20(, ri)6(ght)22( col)6(u)0(mn)20(\). W)8(h)0(e)20(r)-3(e the)20( )-20(same or )-20(si)6(mi)6(l)6(a)20(r )-20(exte)20(rnal)6(i)6(t)2(i)6(e)0(s)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(are pr)16(oduced)19( i)5(n)-1( eve)19(r)-4(y j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1(, )-20(how)5(eve)19(r)-4(, )-20(l)5(o)-1(cal)5( autho)19(ri)5(ti)5(es )-20(may)23( )-20(coope)19(rate )-20(t)21(o)]TJ
+T*
+0.199 Tw
+[(al)5(l)5( )20(i)5(n)-1(crease/)21(reduce)19( exter)16(nal)5(i)5(t)1(i)5(e)-1(s to t)21(he effi)5(ci)5(e)19(n)-1(t l)5(e)-1(vel)5(.)1( )20(Thi)5(s)3( esp)19(e)-1(ci)5(al)5(l)5(y)3( occurs)]TJ
+ET
+endstream endobj 175 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 176 0 obj << /Type /Pages /Kids [ 173 0 R 177 0 R 50 0 R 52 0 R 54 0 R 57 0 R 188 0 R 59 0 R 193 0 R 61 0 R ] /Count 10 /Parent 151 0 R >> endobj 177 0 obj << /Type /Page /Parent 176 0 R /Resources 179 0 R /Contents 178 0 R >> endobj 178 0 obj << /Length 7530 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(21)Tj
+-34.32 58.98 TD
+0.018 Tw
+[(w)6(here they)24( see i)6(t)2( as)24( a re)20(peate)20(d)0( si)6(tuati)6(o)0(n)20(.)2( The)20(y)4( may )20(bel)6(i)6(e)0(ve th)20(at )-20(i)6(f)2( )-20(they)24( )-20(behav)24(e)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(cooper)-5(ativ)22(ely this pe)18(r)-5(i)4(od, o)18(t)0(her)-5(s will r)15(e)-2(cipr)-5(oc)22(ate in th)18(e next.)]TJ
+0 -2.32 TD
+0.059 Tw
+[(A)10(nother )20(cl)5(ea)19(r sou)19(r)-4(ce of p)19(oor )20(deci)5(s)3(i)5(on m)16(a)-1(ki)5(ng a)19(r)-4(i)5(s)3(es w)5(hen )20(the d)19(e)-1(ci)5(si)5(on maki)5(n)19(g)]TJ
+0 -1.14 TD
+0.099 Tw
+[(group )20(i)5(s)3( )20(a)19(b)-1(l)5(e)-1( )20(to )20(i)25(m)-4(pose )20(p)19(a)-1(rt )20(o)19(r)-4( al)5(l)5( of )20(the costs o)19(n)-1( an)19(other)16( gro)19(up \()16(r)-4(ow)5( tw)5(o\).)21( If)]TJ
+0 -1.16 TD
+0.004 Tc
+0.218 Tw
+[(the costs a)20(r)-3(e bo)20(rne by )20(a l)6(a)0(rg)20(er g)20(r)-3(oup t)22(han t)22(he )-20(deci)6(s)4(i)6(o)0(n)20(-mak)24(e)0(rs )-20(\()17(e)0(.g.: )-20(l)6(o)0(c)24(a)0(l)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(deci)5(s)3(i)5(on maki)5(n)19(g)-1( but )20(nati)5(onal)5( c)23(o)-1(st bea)19(ri)5(ng\))16(, and t)21(he be)19(nefi)5(t)1(s fr)16(om )-20(th)19(e )-20(publ)5(i)5(c)]TJ
+T*
+0.3 Tw
+[(good )20(ar)15(e pr)-5(i)24(m)-5(ar)-5(ily local, )20(public go)18(ods will tend )20(to be )20(over)15(-)-5(p)-2(r)-5(o)-2(vid)18(ed. )20(T)-7(h)-2(e)]TJ
+T*
+0.079 Tw
+[(govern)19(m)-4(ent i)5(s)3( n)19(o)-1(t accou)19(n)-1(tabl)5(e t)21(o)-1( i)5(t)1(s \223t)21(axpayers)23(\224)-4(. )-20( )-20(If benefi)5(t)1(s are al)5(so )-20(nati)5(o)19(nal)5(,)]TJ
+0 -1.14 TD
+-0.001 Tc
+0.003 Tw
+[(th)-5(e)-5( d)-5(e)-5(c)-1(isio)-5(n)-5( will o)-5(n)-5(l)1(y )20(r)-8(e)-5(fle)-5(c)-1(t l)21(o)-5(ca)-5(l in)-5(te)15(r)-8(e)-5(sts )-20(a)-5(n)15(d)-5( )-20(th)-5(e)-5( d)-5(e)-5(c)-1(isio)-5(n)-5( )-20(will )-20(b)-5(e)-5( )-20(in)15(e)-5(fficie)-5(n)-5(t)-3( )-20(b)15(u)-5(t)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(not system)-5(a)18(t)0(ically biased.)]TJ
+12 0 2.551 12 99.36 579.44 Tm
+[(N)4(a)-2(ti)4(onal)4( D)4(e)-2(ci)4(si)4(ons)]TJ
+12 0 0 12 99.36 551.84 Tm
+0.139 Tw
+[(C)5(onsi)5(der )20(th)19(e )20(cont)21(rasti)5(ng )20(c)23(a)-1(se, w)5(h)-1(e)19(r)-4(e cent)21(ral)5( gov)23(ern)19(m)-4(ent d)19(e)-1(ter)16(m)-4(i)5(nes a p)19(o)-1(l)5(i)5(c)3(y)]TJ
+T*
+0.039 Tw
+[(for the )20(benefi)5(t)1( )20(of the )20(nati)5(on, )20(and th)19(en r)16(equi)5(res l)25(o)-1(cal)5( gove)19(r)-4(nm)16(ent to i)25(m)-4(pl)5(em)16(ent i)5(t)]TJ
+T*
+[(and bea)19(r the c)23(o)-1(sts \()16(r)-4(ow)5( thr)16(ee, ri)5(g)19(h)-1(t col)5(u)19(mn\). )-20(T)14(h)-1(i)5(s)3( )-20(si)5(tu)19(ati)5(on )-20(i)5(s)3( )-20(r)16(e)-1(fer)16(r)-4(ed )-20(to)19( )-20(as )-20(an)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(\221)6(unfunded)20( )20(man)20(date\222)6(. )20( )20(U)6(n)0(f)22(unded)20( )20(man)20(dates can)20( l)6(ead t)22(o)0( i)6(nequi)6(t)22(abl)6(e cost )20(beari)26(ng,)]TJ
+0 -1.24 TD
+0.003 Tc
+-0.001 Tw
+[(and i)5(neffi)5(ci)5(en)19(t fi)5(nanci)5(n)19(g.)]TJ
+10.08 0 0 10.08 228 498.205 Tm
+0 Tc
+0 Tw
+(8)Tj
+12 0 0 12 233.52 495.2 Tm
+0.003 Tc
+0.019 Tw
+[( )20( )20(A)10(l)5(though )20(al)5(l)5( )20(affec)23(t)1(ed ag)19(ents a)19(r)-4(e l)5(o)-1(cat)21(ed i)5(n)-1( th)19(e cent)21(ral)]TJ
+-11.18 -1.16 TD
+0.299 Tw
+[(govern)19(m)-4(ent j)5(u)19(ri)5(sdi)5(c)3(ti)5(on, cos)23(t)1(s are)19( bor)16(ne by a m)16(i)5(nori)5(t)1(y)23( so )-20(publ)5(i)5(c)3( )-20(c)23(hoi)5(ce )-20(i)5(s)]TJ
+T*
+0 Tw
+[(unbalance)18(d)-2(. P)9(ublic goo)18(ds will tend t)20(o)-2( be ov)22(er)-5(p)18(r)-5(oduce)18(d)-2(.)]TJ
+0 -2.32 TD
+0.199 Tw
+[(If )20(the )20(deci)5(s)3(i)5(o)19(n )20(maki)5(n)19(g)-1( )20(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( i)5(s)3( l)5(a)-1(rg)19(er than)19( the )20(area )20(of the )20(effects, )20(and)]TJ
+0 -1.14 TD
+0.18 Tw
+[(costs ar)-5(e sh)18(ar)-5(ed)18( thr)-5(o)18(ughou)18(t the ju)18(r)-5(i)4(sdiction, th)18(ose )-20(o)18(u)-2(tside )-20(th)18(e )-20(ar)15(ea )-20(will )-20(lose)]TJ
+0 -1.16 TD
+0.039 Tw
+[(from )20(a )20(provi)5(s)3(i)5(o)-1(n)19( to ad)19(dress t)21(he exte)19(rnal)5(i)5(t)1(y th)19(at i)5(n)-1(vol)5(v)3(es )20(publ)5(i)5(c)3( exp)19(endi)5(tur)16(e)-1( \(r)16(ow)]TJ
+T*
+0.24 Tw
+[(four)-5(, left c)22(o)-2(lum)-5(n)18(\))-5(.)0( Rep)18(r)-5(esent)20(atives of t)20(hese )-20(ou)18(tsider)-5(s )-20(will )-20(vot)20(e)-2( )-20(agai)24(nst )-20(the)]TJ
+T*
+0.239 Tw
+[(provi)5(s)3(i)5(on, u)19(n)-1(l)5(e)-1(ss re)19(gul)5(ato)19(r)-4(s make)19( deal)5(s ac)23(ross a)19(r)-4(eas )-20(so al)5(l)5( )-20(l)5(o)-1(cal)5(l)5(y)3( )-20(effi)5(ci)5(ent)]TJ
+0 -1.24 TD
+-0.021 Tw
+[(outcomes are )-20(su)19(ppor)16(ted.)]TJ
+10.08 0 0 10.08 232.08 372.205 Tm
+0 Tc
+0 Tw
+(9)Tj
+12 0 0 12 237.6 369.2 Tm
+0.003 Tc
+-0.001 Tw
+[( In addi)5(ti)5(o)19(n)-1(, vote)19(rs w)5(i)5(t)1(h l)5(i)5(ttl)5(e di)25(rect i)5(n)-1(te)19(rest i)5(n)-1( )20(an i)5(ssue)]TJ
+-11.52 -1.16 TD
+0.004 Tc
+0.118 Tw
+[(may seek to)20( i)6(m)-3(pose)20( thei)6(r )20(pref)22(erences)24( on ot)22(her g)20(r)-3(oups)24( and )-20(a)20(r)-3(eas, parti)6(cul)26(a)0(rl)6(y)]TJ
+T*
+-0.002 Tw
+[(w)6(here they)24( bea)20(r no di)26(rect cost.)]TJ
+0 -2.3 TD
+0.118 Tw
+[(To sum)17(m)-3(ari)6(s)4(e,)22( bal)6(ance)20(d)0( deci)6(s)4(i)6(ons)24( req)20(u)0(i)6(r)-3(e th)20(at thos)24(e that )20(make t)22(he deci)6(s)4(i)6(ons)]TJ
+0 -1.16 TD
+0.498 Tw
+[(are )20(thos)24(e )20(that )20(recei)6(v)4(e t)22(he be)20(nefi)6(t)2(s an)20(d bea)20(r the c)24(o)0(sts. )20(Thi)6(s)4( avoi)6(ds)]TJ
+T*
+0.138 Tw
+[(i)6(n)0(terj)6(uri)6(s)4(di)6(cti)6(o)20(nal)6( exte)20(rnal)6(i)6(t)2(i)6(e)0(s t)22(hat coul)26(d l)6(ead to)20( unde)20(r or)17( )-20(over)17(provi)6(s)4(i)6(on of )-20(the)]TJ
+T*
+0.002 Tc
+0 Tw
+[(good. )20(T)-7(her)15(e m)-5(a)-2(y still b)18(e)-2( unev)22(en cost )20(bear)-5(in)18(g within a ju)18(r)-5(i)4(sdiction.)]TJ
+0 -2.3 TD
+0.019 Tw
+[(In )20(consi)5(deri)25(ng w)5(het)21(her to)19( devol)5(ve )20(deci)5(s)3(i)5(on )20(maki)5(ng th)19(e fol)5(l)5(o)-1(w)5(i)5(ng )20(questi)5(ons)23( need)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(to be consi)5(d)19(ered)19(:)]TJ
+/F12 1 Tf
+0 -2.4 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(here ar)16(e the )20(benefi)5(t)1(s/)21(effects f)21(e)-1(l)5(t)1(?)]TJ
+/F12 1 Tf
+-2.36 -2.38 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+0.219 Tw
+[(W)7(ho bears t)21(he costs c)23(u)-1(rr)16(entl)5(y)3(? Is i)5(t)1( )20(the sa)19(me ar)16(ea th)19(at rec)23(e)-1(i)5(v)3(es )-20(the)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(benefi)5(t)1(s? W)7(h)19(ere co)19(ul)5(d costs )20(more )20(appr)16(opri)5(a)-1(te)19(l)5(y)3( be b)19(o)-1(rne)19(?)]TJ
+-2.36 -1.58 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 144.32 m
+99.366 144.32 l
+S
+BT
+12 0 0 12 200.16 140.24 Tm
+( )Tj
+ET
+243.843 144.32 m
+200.163 144.32 l
+S
+BT
+10.08 0 0 10.08 99.36 128.365 Tm
+0 Tc
+(8)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+0.04 Tw
+[( )-1952(A)-8(n)0( ex)-8(am)-8(ple of)-16( )24(t)-16(his)-8( ar)-8(is)-8(es)-8( in t)-16(h)0(e)24( c)-8(a)0(s)-8(e)0( of)8( s)-8(ignif)-16(ic)-8(ant)-16( )-23(nat)-16(ur)-8(al )-23(ar)-8(eas)-8( )-23(in )-23(Nor)-8(t)-16(hland.)-16( )-23(S)-8(ee )-23(Cas)-8(e)]TJ
+2.2619 -1.1667 TD
+0.016 Tw
+[(S)-8(t)-16(udy)-8( I)8(I)-16(.)]TJ
+-2.8095 -2.2619 TD
+0 Tc
+0 Tw
+(9)Tj
+0.5476 -0.3095 TD
+-0.008 Tc
+1.992 Tw
+[( O)-16(l)0(s)-8(on,)-16( )1976(1980)]TJ
+ET
+endstream endobj 179 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 180 0 obj << /Length 4058 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(22)Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 745.76 Tm
+0.005 Tc
+-0.003 Tw
+[(C)7(o)-4(st e)21(ffec)21(t)-2(ive )20(decis)21(i)3(on)16( m)14(akin)16(g)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 719.6 Tm
+0.003 Tc
+0.099 Tw
+[(One )20(nati)5(o)-1(n)19(a)-1(l)5( )20(pol)5(i)5(cy )20(r)16(equi)5(res)23( )20(onl)5(y on)19(e deci)5(s)3(i)5(on-m)16(a)-1(ki)5(n)19(g)-1( proc)23(ess, so i)5(f)1( t)21(he costs)]TJ
+0 -1.14 TD
+[(of )20(deci)5(s)3(i)5(on )20(maki)5(ng a)19(r)-4(e hi)5(g)19(h)-1(, nati)5(o)19(nal)5( pol)5(i)5(c)3(i)5(e)-1(s sav)23(e)-1( consi)5(d)-1(e)19(r)-4(abl)5(y by)23( cutti)5(ng )20(out)]TJ
+0 -1.16 TD
+0.34 Tw
+[(duplication. Cos)22(t)0(s will be esp)18(e)-2(cially high wher)15(e issues)22( ar)-5(e )20(publicly )-20(ver)-5(y)]TJ
+T*
+-0.001 Tw
+[(contenti)5(ous )20(or i)5(n)-1(vol)5(v)23(e compl)25(e)-1(x i)5(n)-1(for)16(m)-4(ati)5(on )20(and a)19(nal)5(ysi)5(s.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.158 Tw
+[(E)11(v)4(en i)6(f)2( nati)6(onal)6( )20(deci)6(s)4(i)6(on m)17(a)0(ki)6(ng i)6(s)4( m)17(o)0(re )-20(ex)24(pensi)6(v)4(e, a )-20(nati)6(o)20(nal)6( )-20(deci)6(s)4(i)6(on onl)6(y)]TJ
+0 -1.14 TD
+-0.002 Tw
+[(needs to )20(be ma)20(de onc)24(e, w)6(h)0(i)6(l)6(e)0( a )20(regi)6(on)20(al)6( deci)6(s)4(i)6(on )20(must be)20( mad)20(e)0( )-20(16 )-20(ti)26(mes )-20(and)20( )-20(a)]TJ
+0 -1.16 TD
+0.003 Tc
+0.139 Tw
+[(terri)5(to)19(ri)5(al)5( l)5(o)-1(cal)5( au)19(thori)5(t)1(y )20(deci)5(s)3(i)5(on m)16(u)-1(st be )20(made 78 )-20(ti)5(m)16(e)-1(s. )-20( )-20(If )-20(p)19(r)-4(efe)19(r)-4(ences are)]TJ
+T*
+0.579 Tw
+[(nati)5(onal)5(l)5(y)3( ho)19(moge)19(neous, )20(e.g.: a)19(n)-1( i)5(ssue suc)23(h)-1( as dri)25(n)-1(ki)5(ng-w)5(a)-1(t)21(e)-1(r q)19(ual)5(i)5(t)1(y)]TJ
+T*
+0.359 Tw
+[(standards)23(, thi)5(s)3( du)19(pl)5(i)5(c)3(ati)5(on i)5(s)3( w)5(a)-1(st)21(eful)5( eve)19(n)-1( i)5(f)1( each j)25(u)-1(ri)5(sdi)5(c)3(ti)5(on makes an)]TJ
+T*
+0.259 Tw
+[(approp)19(ri)5(ate d)19(e)-1(ci)5(si)5(on. In)19( contr)16(a)-1(st, m)16(a)-1(ki)5(ng m)16(u)-1(l)5(t)1(i)5(p)-1(l)5(e)-1( deci)5(s)3(i)5(ons)23( on )-20(w)5(h)-1(e)19(t)1(her )-20(t)21(o)]TJ
+0 -1.14 TD
+0.099 Tw
+[(constrai)5(n t)21(he styl)5(e o)19(f)1( resi)5(d)19(enti)5(a)-1(l)5( dev)23(el)5(opme)19(n)-1(t, an)19(d i)5(f)1( so how)5(,)21( i)5(s)3( )-20(expensi)5(v)23(e )-20(but)]TJ
+0 -1.16 TD
+0.159 Tw
+[(w)5(o)-1(rthw)5(hi)5(l)5(e)-1( )20(i)5(f)1( p)19(r)-4(efe)19(r)-4(ences va)19(ry si)5(gni)5(fi)5(ca)19(ntl)5(y)3( amo)19(ng j)5(u)-1(ri)5(s)23(d)-1(i)5(c)3(ti)5(ons. On)19(e nati)5(o)19(nal)]TJ
+T*
+0 Tw
+[(decision will lead to )20(poor)15( r)-5(e)-2(p)18(r)-5(esent)20(ation of)20( pr)-5(ef)20(er)-5(enc)22(es.)]TJ
+0 -2.32 TD
+-0.001 Tc
+0.183 Tw
+[(T)-10(h)-5(e)-5( fo)-5(llo)-5(win)15(g)-5( a)-5(r)-8(e)-5( c)19(e)-5(n)-5(t)-3(r)12(a)-5(l in)-5( )-20(a)-5(sse)-5(ssin)-5(g)15( )-20(wh)-5(e)-5(t)-3(h)-5(e)-5(r)12( )-20(co)-5(st e)-5(ffe)-5(ctive)-5(n)15(e)-5(ss )-20(issu)-5(e)-5(s)-1( )-20(will)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(form p)19(a)-1(rt of )20(the d)19(e)-1(ci)5(si)5(on of w)5(h)19(ether)16( to dev)23(ol)5(ve deci)5(s)3(i)5(o)-1(n)19(-maki)5(n)19(g)-1(:)]TJ
+/F12 1 Tf
+0 -2.4 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(Is the cost o)19(f)1( deci)5(s)3(i)5(on )20(maki)5(ng )20(hi)5(gh?)]TJ
+/F12 1 Tf
+-2.36 -2.38 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(Is there )20(homo)19(genei)5(ty o)19(r)-4( het)21(erog)19(enei)5(ty of)21( prefe)19(r)-4(enc)23(es?)]TJ
+/F12 1 Tf
+-2.36 -2.38 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+0.098 Tw
+[(If there )20(are )20(hi)6(gh costs )20(and h)20(e)0(tero)20(geneo)20(us pref)22(ere)20(n)0(ces, how)6( )20(do w)6(e)0( t)22(r)-3(ade)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(these tw)5(o of)21(f? i)5(.)1(e.: )20(how)5( do w)25(e)-1( assess w)5(h)-1(i)5(c)3(h p)19(o)-1(i)5(n)-1(t o)19(n)-1( the )20(graph)19( w)5(e)-1( ar)16(e at?)]TJ
+ET
+endstream endobj 181 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 182 0 obj << /Length 14846 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(23)Tj
+-34.32 58.98 TD
+0.003 Tc
+-0.001 Tw
+[(A)10( case study tha)19(t)1( hi)5(ghl)5(i)5(ghts)23( these i)5(ssu)19(es i)5(s)3( that)21( of cel)5(l)5( ph)19(one tow)25(e)-1(r pl)5(ac)23(ement)21(.)]TJ
+/F3 1 Tf
+11.04 0 0 11.04 99.36 714.315 Tm
+0.006 Tc
+[(EXA)11(M)13(P)-1(L)8(E)-1(:)13( )22( T)8(H)11(E )22(PL)8(A)11(C)11(E)-1(M)13(E)-1(N)11(T)8( )22(OF)8( C)11(E)-1(L)8(L)30( PH)11(ON)11(E)21( T)8(O)1(W)37(E)-1(R)11(S)]TJ
+ET
+1 i
+93.6 726.08 0.48 -0.48 re
+f*
+93.6 726.08 0.48 -0.48 re
+f*
+94.08 726.08 435.84 -0.48 re
+f*
+529.92 726.08 0.48 -0.48 re
+f*
+529.92 726.08 0.48 -0.48 re
+f*
+93.6 725.6 0.48 -25.92 re
+f*
+529.92 725.6 0.48 -25.92 re
+f*
+BT
+/F5 1 Tf
+11.04 0 0 11.04 99.36 689.542 Tm
+0.008 Tc
+0.084 Tw
+[(T)10(he )22(pl)13(ac)30(em)15(e)20(n)-1(t )22(of c)30(e)-1(l)13(l)13( p)20(h)-1(o)20(n)-1(e)20( tow)34(e)-1(r)15(s)8( i)13(n)20( th)20(e c)30(o)-1(m)15(m)15(uni)13(t)25(y)8( )-21(h)20(a)-1(s)8( be)20(en)20( )-21(a )-21(c)30(o)-1(n)20(t)3(r)15(o)-1(v)30(e)-1(r)15(s)8(i)13(a)-1(l)13( )-21(i)13(s)8(s)8(u)20(e)]TJ
+ET
+93.6 699.68 0.48 -12.72 re
+f*
+529.92 699.68 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 676.822 Tm
+0.009 Tc
+0.017 Tw
+[(ov)9(er)16( t)26(h)0(e)21( l)14(a)0(s)9(t)26( c)9(o)21(upl)35(e o)21(f)4( y)31(ear)16(s)9(.)4( )-22(M)16(a)21(ny)9( )-22(m)16(e)0(m)38(ber)16(s)9( of th)21(e )-22(p)21(ubl)14(i)14(c)9( ha)21(v)9(e)0( per)16(c)31(e)0(i)14(v)9(e)21(d)0( )-22(t)26(he )-22(l)35(e)0(v)9(e)0(l)35( )-22(of)]TJ
+ET
+93.6 686.96 0.48 -12.72 re
+f*
+529.92 686.96 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 664.102 Tm
+0.007 Tc
+-0.002 Tw
+[(he)19(al)12(th r)14(i)12(s)7(k)7( i)12(m)36(pos)29(ed)19( by)7( )22(th)19(es)7(e)19( tow)33(e)-2(r)14(s)7( t)24(o)-2( b)19(e)-2( s)7(i)33(gni)12(fi)12(c)29(ant)24(. H)33(o)-2(w)12(e)-2(v)29(e)-2(r)14(,)2( )-21(T)31(he )-21(w)33(e)-2(i)12(g)19(ht of )-21(s)7(c)7(i)33(enti)33(f)2(i)12(c)]TJ
+ET
+93.6 674.24 0.48 -12.72 re
+f*
+529.92 674.24 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 651.382 Tm
+0.008 Tc
+0.301 Tw
+[(opi)13(ni)34(on)20( )-22(i)13(s)8( )-22(th)20(at)25( )-22(th)20(e )-22(r)15(i)13(s)8(k)8( of he)20(al)13(th)20( )-22(pr)15(o)20(b)-1(l)13(e)-1(m)15(s)8( oc)8(c)30(u)-1(r)15(r)15(i)13(ng as)8( a )-22(r)15(e)-1(s)30(u)-1(l)13(t)3( of ex)8(p)20(o)-1(s)8(u)-1(r)37(e)-1( )-22(t)25(o)]TJ
+ET
+93.6 661.52 0.48 -12.72 re
+f*
+529.92 661.52 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 635.302 Tm
+-0.003 Tw
+[(r)15(adi)13(ofr)37(e)-1(q)20(u)-1(e)20(n)-1(c)8(y)8( fi)34(el)13(ds)8( )22(c)8(o)-1(m)15(p)-1(l)13(y)8(i)34(ng w)13(i)13(t)25(h )22(th)20(e N)13(e)-1(w)13( Z)32(eal)13(a)20(n)20(d)-1( s)8(t)25(a)20(n)-1(d)20(a)-1(r)15(d)-1( i)13(s)8( )22(ne)20(gl)13(i)13(g)-1(i)13(b)-1(l)34(e)]TJ
+33.4348 0.2826 TD
+0.009 Tc
+(10)Tj
+1.1304 -0.2826 TD
+0 Tc
+0 Tw
+(.)Tj
+ET
+93.6 648.56 0.48 -15.6 re
+f*
+529.92 648.56 0.48 -15.6 re
+f*
+93.6 632.96 0.48 -12.72 re
+f*
+529.92 632.96 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 610.102 Tm
+0.008 Tc
+0.258 Tw
+[(T)10(e)-1(l)13(e)-1(c)8(o)-1(m)15(m)37(uni)13(c)30(a)-1(ti)13(o)20(n)-1(s)8( c)30(o)-1(m)15(p)20(ani)13(e)20(s)8( t)25(hat)25( w)13(i)13(s)8(h t)25(o)-1( )22(pl)13(ac)30(e )22(a c)8(e)-1(l)13(l)13( s)8(i)13(t)25(e)-1( i)34(n)-1( a)20( )-21(c)8(o)-1(m)15(m)15(u)20(ni)13(ty)8( ar)15(e)]TJ
+ET
+93.6 620.24 0.48 -12.72 re
+f*
+529.92 620.24 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 597.382 Tm
+0.105 Tw
+[(r)15(equi)13(r)15(e)20(d t)25(o)-1( )21(ap)20(pl)13(y)8( f)25(o)-1(r)15( a)20( r)15(e)-1(s)8(o)20(ur)15(c)8(e)20( c)8(o)20(ns)8(e)20(n)-1(t )21(fr)15(om)15( t)25(he l)13(o)20(c)8(a)-1(l)34( a)20(u)-1(th)20(or)15(i)13(t)3(y)8(.)3( )21(Any)30( m)15(e)-1(m)15(b)20(er)15( )-22(o)20(f)3( )-22(t)25(h)-1(e)]TJ
+ET
+93.6 607.52 0.48 -12.72 re
+f*
+529.92 607.52 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 584.662 Tm
+0.009 Tc
+0.039 Tw
+[(pu)21(bl)14(i)14(c)9( c)9(a)21(n )-22(m)16(a)0(k)31(e)0( a )-22(s)31(ubm)16(i)14(s)9(s)9(i)14(o)21(n)0( on a pr)16(ov)9(i)14(s)9(i)14(o)21(n of a )-22(di)14(s)31(t)4(r)16(i)14(c)9(t)4( )-22(or)16( )-22(r)38(egi)14(o)21(nal)35( )-22(pl)14(a)21(n)0( de)21(al)14(i)14(n)0(g)21( )-22(w)14(i)14(t)4(h)]TJ
+ET
+93.6 594.8 0.48 -12.72 re
+f*
+529.92 594.8 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 571.942 Tm
+0.008 Tc
+0.105 Tw
+[(c)8(e)-1(l)13(l)13( )21(p)20(h)-1(o)20(ne )43(tow)34(e)-1(r)15(s)8( )21(or)15( )43(on)20( )21(a)20(n)-1(y)8( p)20(a)-1(r)15(t)3(i)13(c)8(ul)34(ar)15( c)8(e)-1(l)13(l)13( )21(ph)20(on)20(e to)20(w)13(e)-1(r)15( r)37(e)-1(s)8(o)20(ur)15(c)8(e)-1( c)30(o)-1(n)20(s)8(e)20(n)-1(t )21(ap)20(pl)13(i)13(c)8(ati)34(on.)]TJ
+ET
+93.6 582.08 0.48 -12.72 re
+f*
+529.92 582.08 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 559.222 Tm
+0.388 Tw
+[(C)13(ons)30(ents)30( )22(c)8(a)20(n )44(al)13(s)8(o)-1( )44(be)20( a)20(p)-1(p)20(eal)34(ed )22(to )22(th)20(e E)23(n)-1(v)8(i)13(r)15(o)20(nm)15(en)20(t C)13(o)20(ur)15(t. T)32(h)20(e p)20(ubl)13(i)13(c)8( c)30(o)-1(n)20(c)8(er)15(n)]TJ
+ET
+93.6 569.36 0.48 -12.72 re
+f*
+529.92 569.36 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 546.502 Tm
+0.006 Tc
+0.412 Tw
+[(r)13(egar)35(di)11(ng)18( )22(p)18(e)-3(r)13(c)6(ei)11(v)28(ed )44(he)18(al)11(th)18( )22(r)13(i)11(sks )22(h)18(a)-3(s m)35(ani)11(f)23(e)-3(st)23(ed i)11(t)1(s)28(e)-3(l)11(f)1( i)32(n)-3( c)28(onti)32(n)-3(u)18(e)-3(d)18( su)18(bm)13(i)11(ssi)11(ons)]TJ
+ET
+93.6 556.64 0.48 -12.72 re
+f*
+529.92 556.64 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 533.782 Tm
+0.008 Tc
+0.084 Tw
+[(op)20(pos)8(i)34(ng )22(th)20(e gr)37(anti)34(n)-1(g)20( of)25( r)15(e)-1(s)8(o)20(ur)15(c)8(e)20( c)8(o)20(ns)8(e)20(n)-1(ts)8( )22(for)15( c)30(e)-1(l)13(l)13( s)8(i)13(te)20(s)8( a)20(n)-1(d)20( a )22(num)37(ber)15( )22(of )22(pe)20(ti)13(ti)13(o)20(n)-1(s)8( )-21(t)25(o)]TJ
+ET
+93.6 543.92 0.48 -12.72 re
+f*
+529.92 543.92 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 521.062 Tm
+-0.003 Tw
+[(the)20( E)23(n)-1(v)8(i)13(r)15(onm)37(ent)25( C)13(o)20(ur)15(t.)]TJ
+ET
+93.6 531.2 0.48 -12.72 re
+f*
+529.92 531.2 0.48 -12.72 re
+f*
+93.6 518.48 0.48 -12.72 re
+f*
+529.92 518.48 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 495.622 Tm
+0.04 Tw
+[(T)10(he )22(j)34(u)-1(d)20(gem)37(ent)25( )22(th)20(at )43(ne)20(e)20(d)-1(s)8( )22(t)25(o)-1( b)20(e)-1( m)37(a)-1(d)20(e)-1( i)13(n)-1( )22(thi)13(s)8( )22(c)8(a)-1(s)30(e)-1( s)8(t)25(udy)30( i)13(s)8( t)25(he w)34(e)-1(i)13(g)20(hti)13(n)20(g w)34(h)-1(i)13(c)8(h s)30(h)-1(o)20(u)-1(l)13(d)]TJ
+ET
+93.6 505.76 0.48 -12.72 re
+f*
+529.92 505.76 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 483.142 Tm
+0.009 Tc
+0.257 Tw
+[(be )44(pl)14(ac)31(ed)21( )22(o)21(n)0( )22(e)21(n)0(s)31(u)0(r)16(i)14(ng )22(th)21(at l)35(o)0(c)9(a)0(l)14( )22(pr)16(ef)26(er)16(e)21(n)0(c)9(e)0(s)31( ar)16(e)21( i)14(n)0(c)9(l)14(u)21(d)0(e)21(d)0( i)35(n)0( t)26(he )22(de)21(c)9(i)14(s)9(i)14(on)21( m)16(a)0(k)9(i)14(n)21(g)]TJ
+ET
+93.6 493.28 0.48 -12.72 re
+f*
+529.92 493.28 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 470.422 Tm
+0.008 Tc
+0.04 Tw
+[(pr)15(oc)8(es)30(s)8(,)3( )22(bas)30(ed)20( o)20(n)-1( t)25(he c)30(o)-1(s)8(t)3(s)30( a)20(n)-1(d)20( b)20(e)-1(n)20(e)-1(fi)13(ts)8( )22(of )22(th)20(ei)13(r)15( i)13(n)-1(c)8(l)13(us)8(i)34(on.)25( T)32(he )22(be)20(ne)20(fi)13(t o)20(f)3( )-22(c)30(ons)8(i)34(der)15(i)13(n)20(g)]TJ
+ET
+93.6 480.56 0.48 -12.72 re
+f*
+529.92 480.56 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 457.702 Tm
+0.084 Tw
+[(l)13(o)-1(c)8(a)-1(l)13( )44(pr)15(ef)25(er)15(enc)30(es)8( )22(i)13(s)30( )22(th)20(at )44(th)20(e r)15(e)-1(s)30(u)-1(l)13(t)3(i)13(n)20(g r)15(e)20(gi)13(o)20(nal)13( s)30(t)3(a)20(n)-1(d)20(a)-1(r)15(d)-1( i)13(s)8( m)37(o)-1(r)15(e)-1( l)13(i)13(k)30(el)13(y)8( to)20( b)20(e)-1( )22(a g)20(e)-1(n)20(u)-1(i)13(n)20(e)]TJ
+ET
+93.6 467.84 0.48 -12.72 re
+f*
+529.92 467.84 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 444.982 Tm
+0.344 Tw
+[(r)15(e)-1(fl)13(ec)8(ti)34(on )21(of )21(th)20(e pr)37(ef)25(er)15(enc)30(es)8( )21(of )21(th)20(e m)15(e)-1(m)37(ber)15(s)8( )21(of t)25(h)-1(a)20(t)3( c)30(o)-1(m)15(m)15(uni)13(t)25(y)8(. T)32(h)-1(e)20( )-22(c)8(o)-1(s)30(t)3(s)8( )-22(o)20(f)]TJ
+ET
+93.6 455.12 0.48 -12.72 re
+f*
+529.92 455.12 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 432.262 Tm
+0.009 Tc
+0.235 Tw
+[(c)9(ons)9(i)35(der)16(i)14(n)21(g )22(l)14(o)0(c)31(a)0(l)14( )44(pr)16(ef)26(er)16(enc)31(es)9( )44(ar)16(e )44(th)21(at )44(an )22(i)14(s)9(s)31(u)21(e h)21(a)0(s)9( t)26(o)0( )22(be)21( c)9(o)21(ns)9(i)14(d)21(er)16(ed)21( m)16(a)21(ny)9( ti)14(m)16(e)0(s)31(,)]TJ
+ET
+93.6 442.4 0.48 -12.72 re
+f*
+529.92 442.4 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 419.542 Tm
+-0.003 Tc
+0.008 Tw
+[(mu)-12(lt)-8(ip)-12(lyin)9(g)-12( d)9(e)-12(cisio)9(n)-12(-ma)-12(kin)9(g)-12( c)19(o)-12(st)-8(s.)14( Fig)-12(u)-12(r)26(e)-12( xxx)19( illu)-12(st)-8(ra)-12(t)14(e)-12(s )22(t)-8(h)9(e)-12( n)9(a)-12(t)14(u)-12(re)-12( )22(o)-12(f)-8( t)14(h)-12(is t)-8(r)26(a)-12(d)9(e)-12(-)4(o)-12(f)14(f)-8(.)]TJ
+ET
+93.6 429.68 0.48 -12.72 re
+f*
+529.92 429.68 0.48 -12.72 re
+f*
+93.6 416.96 0.48 -12.72 re
+f*
+529.92 416.96 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 394.102 Tm
+0 Tc
+0.026 Tw
+[(On)-9( Fig)12(u)-9(r)7(e)12( xxx, w)26(e)-9( )21(h)-9(a)-9(v)22(e)-9( in)12(d)-9(i)5(ca)-9(t)17(e)12(d)-9( t)17(h)-9(a)-9(t)17( th)12(e)-9( iss)22(u)-9(e)-9( )21(o)-9(f)-5( )21(ce)-9(ll sit)17(e)-9(s c)22(o)-9(u)-9(l)26(d)-9( b)12(e)-9( p)-9(l)5(a)-9(c)22(e)-9(d)-9( o)-9(n)12( )-22(th)12(e)-9( )-22(l)26(e)-9(ft)]TJ
+ET
+93.6 404.24 0.48 -12.72 re
+f*
+529.92 404.24 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 381.382 Tm
+0.008 Tc
+0.084 Tw
+[(en)20(d )22(o)20(f)3( t)25(he )22(s)8(p)20(ec)8(tr)15(um)15( )22(for)15( )22(het)25(er)15(o)20(g)-1(e)20(nei)13(ty)30( of)25( pr)15(e)20(f)3(er)37(enc)8(e)20(s)8(. )22( T)10(h)-1(i)13(s)8( r)15(e)20(pr)15(es)30(en)20(ts)8( t)25(h)-1(e)20( j)13(u)-1(d)20(gem)37(en)20(t)]TJ
+ET
+93.6 391.52 0.48 -12.72 re
+f*
+529.92 391.52 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 368.662 Tm
+0.062 Tw
+[(tha)20(t, )-22(i)13(f)3( pe)20(o)20(p)-1(l)13(e)-1( ar)15(e ex)8(p)20(o)-1(s)8(e)20(d )-22(t)25(o)-1( th)20(e )-22(r)15(e)-1(l)13(e)20(v)8(a)20(nt obj)13(e)20(c)8(ti)13(v)8(e)20( )-22(i)13(n)-1(f)25(o)-1(r)15(m)15(a)-1(ti)13(o)20(n)-1( on )-22(th)20(e )-22(he)20(al)13(th )-43(r)15(i)13(s)8(k)8(s)30( )-43(of)]TJ
+ET
+93.6 378.8 0.48 -12.72 re
+f*
+529.92 378.8 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 355.942 Tm
+-0.001 Tc
+0.049 Tw
+[(ce)-10(ll-)6(site)-10(s, )22(th)11(e)-10(r)6(e)-10( is lik)21(e)-10(l)4(y t)16(o)-10( b)11(e)-10( )22(a)-10( lo)-10(w l)25(e)-10(ve)-10(l )22(o)-10(f)-6( )22(va)-10(r)6(i)4(a)11(n)-10(ce)11( a)-10(c)-1(r)6(o)11(ss )-22(co)-10(m)6(m)28(u)-10(n)-10(i)4(ti)25(e)-10(s)-1( )-22(f)16(o)-10(r)6( )-22(t)16(h)-10(e)-10( )-22(l)25(e)-10(ve)-10(ls)]TJ
+ET
+93.6 366.08 0.48 -12.72 re
+f*
+529.92 366.08 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 343.222 Tm
+-0.004 Tc
+0.009 Tw
+[(o)-13(f)-9( risk f)-9(r)25(o)-13(m)3( ra)-13(d)-13(i)22(o)-13(f)-9(re)8(q)-13(u)8(e)-13(n)-13(c)18(y e)-13(x)18(p)-13(o)8(su)-13(re)8( t)-9(h)8(a)-13(t)-9( )22(p)-13(e)8(o)8(p)-13(le)-13( )22(a)-13(r)3(e)-13( willin)-13(g)8( t)-9(o)8( a)-13(c)-4(c)18(e)-13(p)8(t)-9(.)]TJ
+ET
+93.6 353.36 0.48 -12.72 re
+f*
+529.92 353.36 0.48 -12.72 re
+f*
+93.6 340.64 0.48 -12.72 re
+f*
+529.92 340.64 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 317.782 Tm
+0.008 Tc
+0.062 Tw
+[(F)10(i)13(gur)15(e )22(x)30(x)8(x)8( )22(al)13(s)30(o)-1( )22(s)30(how)13(s)30( th)20(at )22(th)20(er)15(e )22(ar)15(e )22(hi)13(g)20(h)-1( fi)13(x)30(ed c)30(o)-1(s)8(t)3(s)30( of)25( l)13(o)-1(c)30(a)-1(l)13( d)20(e)-1(c)8(i)13(s)8(i)13(o)20(n)-1(-)15(m)15(a)-1(k)8(i)13(n)20(g)-1(. T)32(h)20(es)8(e)]TJ
+ET
+93.6 327.92 0.48 -12.72 re
+f*
+529.92 327.92 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 305.062 Tm
+0.344 Tw
+[(ar)15(e c)30(o)-1(s)8(t)3(s)8( )21(to )21(th)20(e a)20(p)20(p)-1(l)13(i)13(c)8(an)20(t i)13(n)-1( de)20(fe)20(ndi)34(ng ea)20(c)8(h)-1( )-22(i)34(ndi)13(v)8(i)13(d)20(u)20(a)-1(l)13( )-22(c)8(e)-1(l)13(l)13(-)15(s)8(i)13(te)20( )-22(a)20(ppl)13(i)13(c)8(a)20(t)3(i)13(o)20(n, an)20(d)]TJ
+ET
+93.6 315.2 0.48 -12.72 re
+f*
+529.92 315.2 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 292.342 Tm
+0.127 Tw
+[(adm)15(i)13(n)-1(i)13(s)8(tr)37(ati)13(v)8(e)20( )22(c)8(o)-1(s)30(t)3(s)8( f)25(o)-1(r)15( e)20(a)-1(c)8(h)20( s)8(e)20(par)37(ate)20( l)13(o)-1(c)30(a)-1(l)13( a)20(u)-1(th)20(or)15(i)13(t)3(y)8(,)3( )22(an)20(d f)25(o)-1(r)15( t)25(h)-1(e)20( E)23(n)-1(v)8(i)13(r)15(onm)37(ent)25( C)13(o)20(ur)15(t)]TJ
+ET
+93.6 302.48 0.48 -12.72 re
+f*
+529.92 302.48 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 279.622 Tm
+0.009 Tc
+-0.004 Tw
+[(w)14(hen)21( l)14(o)0(c)31(a)0(l)14( d)21(e)0(c)9(i)14(s)9(i)14(o)21(n)0(s)9( )22(ar)16(e )22(ap)21(pe)21(al)14(e)21(d)0(.)]TJ
+ET
+93.6 289.76 0.48 -12.72 re
+f*
+529.92 289.76 0.48 -12.72 re
+f*
+93.6 263.36 0.48 -0.48 re
+f*
+93.6 263.36 0.48 -0.48 re
+f*
+94.08 263.36 435.84 -0.48 re
+f*
+529.92 263.36 0.48 -0.48 re
+f*
+529.92 263.36 0.48 -0.48 re
+f*
+93.6 277.04 0.48 -13.68 re
+f*
+529.92 277.04 0.48 -13.68 re
+f*
+BT
+12 0 0 12 99.36 171.92 Tm
+0.002 Tc
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+200.166 176 m
+99.366 176 l
+S
+BT
+12 0 0 12 200.16 171.92 Tm
+( )Tj
+ET
+243.843 176 m
+200.163 176 l
+S
+BT
+10.08 0 0 10.08 99.36 160.045 Tm
+-0.008 Tc
+(10)Tj
+12 0 0 12 110.4 157.04 Tm
+0 Tc
+( )Tj
+10.08 0 0 10.08 127.68 156.925 Tm
+-0.008 Tc
+0.04 Tw
+[(Cell s)-8(i)0(t)-16(e)0(s)-8( gener)-8(at)-16(e a r)-8(adiof)-16(r)-8(equenc)-8(y)-8( f)-16(ield.)-16( )24(A)-8(t)-16( )24(v)-8(e)0(r)-8(y)-8( high lev)-8(els)-8( of)8( ex)-8(pos)-8(ur)-8(e t)-16(o)0( )24(t)-16(hes)-8(e )-23(f)-16(ields)-8(,)]TJ
+0 -1.1667 TD
+0.087 Tw
+[(adv)-8(er)-8(s)-8(e)0( )24(ef)-16(f)-16(e)0(c)-8(t)8(s)-8( on hum)-8(ans)-8( hav)-8(e been obs)-8(er)-8(v)-8(ed.)8( )24(T)-16(he New Z)-16(ealand v)-8(olunt)-16(ar)-8(y)-8( s)16(t)-16(andar)-8(d,)]TJ
+0 -1.1429 TD
+0.182 Tw
+[(pr)-8(oduc)-8(ed by)-8( S)-8(t)-16(andar)-8(ds)-8( New Z)-16(ealand,)-16( r)-8(e)0(c)-8(o)0(m)15(m)-8(ends)-8( t)-16(hat)8( )-24(ex)-8(pos)-8(ur)-8(e )-24(lim)-8(it)-16(s)-8( f)-16(o)0(r)-8( t)-16(he )-24(public)]TJ
+T*
+0.159 Tw
+[(s)-8(hould )24(be )24(at)-16( )24(leas)-8(t)-16( )24(f)-16(i)0(f)8(t)-16(y)-8( )48(t)-16(i)0(m)-8(e)0(s)-8( )24(lower)-8( )24(t)-16(han t)-16(he lev)-8(els)-8( at)8( whic)-8(h adv)-8(er)-8(s)-8(e)0( ef)8(f)-16(e)0(c)-8(t)-16(s)16( hav)-8(e been)]TJ
+0 -1.1667 TD
+0.111 Tw
+[(ident)-16(if)-16(ied )24(and )24(c)-8(ell )24(s)-8(i)0(t)-16(e)0(s)-8( )24(oper)-8(at)-16(e )24(at)-16( )24(lev)-8(els)-8( )24(of)8( )24(only)-8( a f)-16(e)0(w)23( per)-8(c)-8(ent)-16( of)8( t)-16(he lim)-8(it)-16(s)16( s)-8(t)-16(a)24(t)-16(ed in t)-16(h)0(e)]TJ
+0 -1.1429 TD
+[(s)-8(t)-16(andar)-8(d.)]TJ
+ET
+endstream endobj 183 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 184 0 obj << /Length 11897 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(24)Tj
+/F3 1 Tf
+11.04 0 0 11.04 99.36 720.075 Tm
+0.006 Tc
+-0.001 Tw
+[(EXA)11(M)13(P)-1(L)8(E)-1(:)13( T)8(H)32(E )22(PL)8(A)11(C)11(E)-1(M)13(E)-1(N)11(T)8( )22(OF)8( C)11(E)-1(L)8(L)8( )22(PH)11(ON)11(E )22(T)8(O)1(W)15(E)-1(R)32(S)-1( C)11(O)1(N)11(T)8(IN)11(U)32(E)-1(D)]TJ
+ET
+1 i
+93.6 731.84 0.48 -0.48 re
+f*
+93.6 731.84 0.48 -0.48 re
+f*
+94.08 731.84 435.84 -0.48 re
+f*
+529.92 731.84 0.48 -0.48 re
+f*
+529.92 731.84 0.48 -0.48 re
+f*
+93.6 731.36 0.48 -14.16 re
+f*
+529.92 731.36 0.48 -14.16 re
+f*
+93.6 717.44 0.48 -14.4 re
+f*
+529.92 717.44 0.48 -14.4 re
+f*
+BT
+12 0 0 12 99.36 691.796 Tm
+0.007 Tc
+-0.025 Tw
+[(Fi)5(gur)16(e xxx)]TJ
+ET
+93.6 703.04 0.48 -14.4 re
+f*
+529.92 703.04 0.48 -14.4 re
+f*
+93.6 688.64 0.48 -13.92 re
+f*
+529.92 688.64 0.48 -13.92 re
+f*
+q
+99.36 434.72 424.8 208.8 re
+W n
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+165.6 643.76 m
+165.6 435.2 l
+S
+Q
+168.48 640.64 m
+165.6 641.84 l
+162.48 640.64 l
+165.6 650.48 l
+168.48 640.64 l
+f*
+q
+165.6 390.08 304.32 284.64 re
+W n
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+165.36 435.44 m
+469.44 435.44 l
+S
+Q
+466.8 432.32 m
+468 435.44 l
+466.8 438.56 l
+476.64 435.44 l
+466.8 432.32 l
+f*
+BT
+/F7 1 Tf
+15.36 0 0 15.36 103.92 631.278 Tm
+0.003 Tc
+[(Tot)8(a)3(l)]TJ
+0 -1.2031 TD
+0 Tc
+(Cost)Tj
+20.7812 -12.5469 TD
+0.002 Tc
+[(He)9(t)-9(e)9(r)9(oge)-7(n)11(e)-7(it)7(y)]TJ
+0 -1.2031 TD
+-0.007 Tc
+0.007 Tw
+[( o)-7(f)-2( p)-13(r)0(e)-16(f)-2(er)-16(en)-13(ce)-16(s)]TJ
+ET
+1 1 1 RG
+1 J 1 j 0.72 w 10 M []0 d
+165.6 519.92 m
+465.12 542.96 l
+S
+0 0 0 RG
+165.6 519.92 m
+465.12 542.96 l
+S
+1 1 1 RG
+165.6 446.96 m
+453.6 612.08 l
+S
+0 0 0 RG
+165.6 446.96 m
+453.6 612.08 l
+S
+BT
+11.52 0 0 11.52 403.68 661.939 Tm
+0 Tc
+0 Tw
+[(Total)7( C)-7(o)0(s)-7(t)0( of )]TJ
+0 -1.2083 TD
+[(N)-7(ati)7(on)-7(al)7( D)-7(e)6(c)6(i)-14(s)14(i)-14(on)]TJ
+/F11 1 Tf
+0 -1.1823 TD
+[(\(i)7(nc)-14(orre)6(c)6(t)-14( re)6(fl)7(e)6(c)-14(t)7(i)7(o)0(n)]TJ
+0 -1.2083 TD
+[( of pre)6(fe)-14(re)6(nc)6(e)6(s)-7(\))]TJ
+/F7 1 Tf
+2.0833 -8.0677 TD
+[(Total)7( C)-7(o)0(s)-7(t)0( of s)14(u)-7(m )]TJ
+0 -1.2083 TD
+[(of Loc)6(al)-14( D)14(e)-14(c)6(i)7(s)-7(i)7(on)-7(s)]TJ
+/F11 1 Tf
+0 -1.1823 TD
+[(\(c)6(os)-7(t)7(s)-7( of re)6(pe)-14(t)7(i)7(t)-14(i)7(on\))]TJ
+ET
+311.04 435.2 0.72 0.72 re
+f*
+311.04 437.84 0.72 0.72 re
+f*
+311.04 440.48 0.72 0.48 re
+f*
+311.04 442.88 0.72 0.72 re
+f*
+311.04 445.52 0.72 0.72 re
+f*
+311.04 448.16 0.72 0.48 re
+f*
+311.04 450.56 0.72 0.72 re
+f*
+311.04 453.2 0.72 0.72 re
+f*
+311.04 455.84 0.72 0.48 re
+f*
+311.04 458.24 0.72 0.72 re
+f*
+311.04 460.88 0.72 0.72 re
+f*
+311.04 463.52 0.72 0.48 re
+f*
+311.04 465.92 0.72 0.72 re
+f*
+311.04 468.56 0.72 0.72 re
+f*
+311.04 471.2 0.72 0.48 re
+f*
+311.04 473.6 0.72 0.72 re
+f*
+311.04 476.24 0.72 0.72 re
+f*
+311.04 478.88 0.72 0.48 re
+f*
+311.04 481.28 0.72 0.72 re
+f*
+311.04 483.92 0.72 0.72 re
+f*
+311.04 486.56 0.72 0.48 re
+f*
+311.04 488.96 0.72 0.72 re
+f*
+311.04 491.6 0.72 0.72 re
+f*
+311.04 494.24 0.72 0.48 re
+f*
+311.04 496.64 0.72 0.72 re
+f*
+311.04 499.28 0.72 0.72 re
+f*
+311.04 501.92 0.72 0.48 re
+f*
+311.04 504.32 0.72 0.72 re
+f*
+311.04 506.96 0.72 0.72 re
+f*
+311.04 509.6 0.72 0.48 re
+f*
+311.04 512 0.72 0.72 re
+f*
+311.04 514.64 0.72 0.72 re
+f*
+311.04 517.28 0.72 0.48 re
+f*
+311.04 519.68 0.72 0.72 re
+f*
+311.04 522.32 0.72 0.72 re
+f*
+311.04 524.96 0.72 0.48 re
+f*
+311.04 527.36 0.72 0.72 re
+f*
+311.04 530 0.72 0.72 re
+f*
+311.04 532.64 0.72 0.48 re
+f*
+311.04 535.04 0.72 0.72 re
+f*
+311.04 537.68 0.72 0.72 re
+f*
+311.04 540.32 0.72 0.48 re
+f*
+311.04 542.72 0.72 0.72 re
+f*
+311.04 545.36 0.72 0.72 re
+f*
+311.04 548 0.72 0.48 re
+f*
+311.04 550.4 0.72 0.72 re
+f*
+311.04 553.04 0.72 0.72 re
+f*
+311.04 555.68 0.72 0.48 re
+f*
+311.04 558.08 0.72 0.72 re
+f*
+311.04 560.72 0.72 0.72 re
+f*
+311.04 563.36 0.72 0.48 re
+f*
+311.04 565.76 0.72 0.72 re
+f*
+311.04 568.4 0.72 0.72 re
+f*
+311.04 571.04 0.72 0.48 re
+f*
+311.04 573.44 0.72 0.72 re
+f*
+311.04 576.08 0.72 0.72 re
+f*
+311.04 578.72 0.72 0.48 re
+f*
+311.04 581.12 0.72 0.72 re
+f*
+311.04 583.76 0.72 0.72 re
+f*
+311.04 586.4 0.72 0.48 re
+f*
+311.04 588.8 0.72 0.72 re
+f*
+311.04 591.44 0.72 0.72 re
+f*
+311.04 594.08 0.72 0.48 re
+f*
+311.04 596.48 0.72 0.72 re
+f*
+311.04 599.12 0.72 0.72 re
+f*
+311.04 601.76 0.72 0.48 re
+f*
+311.04 604.16 0.72 0.72 re
+f*
+311.04 606.8 0.72 0.72 re
+f*
+311.04 609.44 0.72 0.48 re
+f*
+311.04 611.84 0.72 0.72 re
+f*
+311.04 614.48 0.72 0.72 re
+f*
+311.04 617.12 0.72 0.48 re
+f*
+311.04 619.52 0.72 0.72 re
+f*
+311.04 622.16 0.72 0.72 re
+f*
+311.04 624.8 0.72 0.48 re
+f*
+311.04 627.2 0.72 0.72 re
+f*
+311.04 629.84 0.72 0.72 re
+f*
+311.04 632.48 0.72 0.48 re
+f*
+311.04 634.88 0.72 0.72 re
+f*
+311.04 637.52 0.72 0.72 re
+f*
+311.04 640.16 0.72 0.48 re
+f*
+311.04 642.56 0.72 0.72 re
+f*
+311.04 645.2 0.72 0.72 re
+f*
+311.04 647.84 0.72 0.48 re
+f*
+311.04 650.24 0.72 0.72 re
+f*
+311.04 652.88 0.72 0.72 re
+f*
+311.04 655.52 0.72 0.48 re
+f*
+311.04 657.92 0.72 0.72 re
+f*
+311.04 660.56 0.72 0.72 re
+f*
+BT
+15.36 0 0 15.36 203.76 397.197 Tm
+[(Na)-9(t)12(i)-3(ona)-9(l)12( Loc)-9(a)7(l)]TJ
+ET
+q
+196.08 390.08 108.24 284.64 re
+W n
+1 1 1 RG
+303.84 416.24 m
+195.84 416.24 l
+S
+0 0 0 RG
+303.84 416.24 m
+195.84 416.24 l
+S
+Q
+197.28 418.4 m
+196.56 416.24 l
+197.28 414.08 l
+192.48 416.24 l
+197.28 418.4 l
+f*
+q
+315.36 390.08 96.96 284.64 re
+W n
+1 1 1 RG
+315.12 416.24 m
+411.84 416.24 l
+S
+0 0 0 RG
+315.12 416.24 m
+411.84 416.24 l
+S
+Q
+410.4 414.08 m
+411.12 416.24 l
+410.4 418.4 l
+415.2 416.24 l
+410.4 414.08 l
+f*
+1 1 1 RG
+199.67 436.318 m
+223.491 441.786 241.9 501.638 241.92 573.682 c
+S
+0 0 0 RG
+199.67 436.318 m
+223.491 441.786 241.9 501.638 241.92 573.682 c
+S
+200.64 438.56 m
+200.16 436.4 l
+201.36 434.48 l
+196.32 435.68 l
+200.64 438.56 l
+f*
+0 0.8 0.6 rg
+1 1 1 RG
+284.04 591.2 m
+284.04 591.2 l
+284.04 598.42 266.138 604.28 244.08 604.28 c
+222.022 604.28 204.12 598.42 204.12 591.2 c
+204.12 583.98 222.022 578.12 244.08 578.12 c
+266.138 578.12 284.04 583.98 284.04 591.2 c
+b*
+0 0 0 RG
+284.04 591.2 m
+284.04 591.2 l
+284.04 598.42 266.138 604.28 244.08 604.28 c
+222.022 604.28 204.12 598.42 204.12 591.2 c
+204.12 583.98 222.022 578.12 244.08 578.12 c
+266.138 578.12 284.04 583.98 284.04 591.2 c
+s
+BT
+15.36 0 0 15.36 211.44 585.357 Tm
+0 0 0 rg
+0.003 Tc
+-0.003 Tw
+[(Ce)10(ll si)15(te)-6(s)17(?)]TJ
+ET
+93.6 674.72 0.48 -284.64 re
+f*
+529.92 674.72 0.48 -284.64 re
+f*
+93.6 390.32 0.48 -13.92 re
+f*
+529.92 390.32 0.48 -13.92 re
+f*
+BT
+/F5 1 Tf
+11.04 0 0 11.04 99.36 366.262 Tm
+0.008 Tc
+0.127 Tw
+[(T)10(he l)34(o)-1(w)13( l)13(e)-1(v)30(e)-1(l)13( o)20(f)3( h)20(e)-1(t)25(e)-1(r)15(o)20(ge)20(nei)13(ty)30( )-22(m)15(e)-1(a)20(n)-1(s)8( th)20(at any)8( )-22(w)34(e)-1(l)13(f)25(ar)15(e )-22(c)30(o)-1(s)8(t)3(s)8( ge)20(ner)37(ate)20(d)-1( by)8( )-22(i)13(m)15(p)20(o)-1(s)8(i)13(n)20(g)]TJ
+ET
+93.6 376.4 0.48 -12.72 re
+f*
+529.92 376.4 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 353.542 Tm
+0.062 Tw
+[(on)20(e d)20(e)-1(c)8(i)13(s)8(i)13(o)20(n)-1( )22(on )22(a r)15(a)20(ng)20(e )22(of )22(di)13(ff)25(er)15(en)20(t c)30(o)-1(m)15(m)15(uni)13(ti)34(es)8( i)13(s)8( )-22(l)34(o)-1(w)13(.)3( )-22( )-22(M)37(e)-1(a)20(n)-1(w)13(h)-1(i)13(l)13(e)-1( n)20(a)-1(ti)13(o)20(nal)13( dec)8(i)13(s)8(i)34(o)-1(n)]TJ
+ET
+93.6 363.68 0.48 -12.72 re
+f*
+529.92 363.68 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 340.822 Tm
+0.007 Tc
+0.476 Tw
+[(m)14(a)-2(k)7(i)12(ng)19( gr)14(e)19(a)-2(tl)12(y)7( r)36(e)-2(d)19(u)-2(c)7(e)-2(s)29( th)19(e )22(adm)14(i)12(n)-2(i)12(s)29(tr)14(ati)12(o)19(n c)29(o)-2(s)7(t)2(s)7( )22(of r)36(e)-2(p)19(e)-2(ti)12(ti)12(v)29(e)-2( )-22(d)19(e)-2(c)7(i)12(s)7(i)12(o)19(n)-2( )-22(m)14(a)-2(k)7(i)33(ng)19(.)]TJ
+ET
+93.6 350.96 0.48 -12.72 re
+f*
+529.92 350.96 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 328.102 Tm
+0.008 Tc
+0.366 Tw
+[(T)10(her)15(e)20(f)3(or)15(e)20( o)20(u)-1(r)15( v)8(i)13(ew)13( i)13(s)8( )22(th)20(at )22(dec)8(i)13(s)8(i)34(ons)30( o)20(n)-1( )-22(t)25(he he)20(al)13(t)25(h)-1( )-22(e)20(ffec)30(t)3(s)8( of )-22(c)30(e)-1(l)13(l)13( )-22(p)20(h)-1(o)20(n)-1(e)20( )-22(tow)34(e)-1(r)]TJ
+ET
+93.6 338.24 0.48 -12.72 re
+f*
+529.92 338.24 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 315.382 Tm
+-0.003 Tw
+[(pl)13(ac)8(em)37(en)20(ts)8( s)30(h)-1(o)20(u)-1(l)13(d)-1( )22(be)20( m)15(a)-1(d)20(e)-1( )22(at t)25(h)20(e n)20(a)-1(ti)13(o)20(nal)34( l)13(e)-1(v)30(e)-1(l)13(.)]TJ
+ET
+93.6 325.52 0.48 -12.72 re
+f*
+529.92 325.52 0.48 -12.72 re
+f*
+93.6 312.8 0.48 -12.72 re
+f*
+529.92 312.8 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 289.942 Tm
+0.236 Tw
+[(T)10(he R)13(M)15(A)23( d)20(oes)30( pr)15(o)20(v)8(i)13(d)-1(e)20( for)15( )22(na)20(ti)13(o)20(nal)13( )22(pol)13(i)13(c)8(y)8( s)30(e)-1(tti)34(ng)20(. C)34(entr)37(a)-1(l)13( g)20(o)-1(v)8(e)-1(r)37(n)-1(m)15(e)-1(n)20(t)3( )-22(c)30(an )-22(m)37(a)-1(k)8(e)]TJ
+ET
+93.6 300.08 0.48 -12.72 re
+f*
+529.92 300.08 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 277.222 Tm
+-0.003 Tw
+[(nati)34(o)-1(n)20(a)-1(l)13( p)20(o)-1(l)13(i)13(c)8(y)8( s)8(t)25(at)25(em)15(en)20(ts)8( \()15(s)8(ec)30( 4)20(5)-1(-)15(5)20(5\))15( or)15( )-21(s)30(e)-1(t na)20(ti)13(on)20(al)13( env)8(i)13(r)15(o)20(n)-1(m)15(e)20(ntal)13( s)8(t)3(a)20(n)-1(d)20(a)-1(r)15(d)-1(s)30( )-21(\()15(s)8(ec)8( 43\))]TJ
+ET
+93.6 287.36 0.48 -12.72 re
+f*
+529.92 287.36 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 264.502 Tm
+[(r)15(equi)13(r)15(i)13(n)20(g)-1( l)13(o)-1(c)30(a)-1(l)13( )22(gov)30(er)15(nm)15(e)20(n)-1(t )22(to )22(de)20(al)13( w)13(i)13(t)25(h t)25(h)-1(i)13(s)8( i)13(s)8(s)8(u)20(e i)13(n)20( a )22(c)8(e)-1(r)15(t)3(ai)34(n f)25(a)-1(s)30(h)-1(i)13(o)-1(n)20(.)]TJ
+ET
+93.6 274.64 0.48 -12.72 re
+f*
+529.92 274.64 0.48 -12.72 re
+f*
+93.6 261.92 0.48 -12.72 re
+f*
+529.92 261.92 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 239.062 Tm
+0.127 Tw
+[(T)10(he l)13(i)13(k)30(el)13(i)13(h)-1(o)20(o)-1(d)20( th)20(at i)34(ndi)13(v)8(i)34(du)20(al)13(s)8( ar)37(e n)20(o)-1(t )22(ac)8(c)30(u)-1(r)15(a)-1(t)25(e)-1(l)13(y)8( es)30(ti)13(m)15(a)-1(ti)13(n)20(g)-1( t)25(h)20(e l)13(e)-1(v)30(e)-1(l)13( )-22(o)20(f)3( )-22(r)15(i)13(s)8(k)8( )-22(i)13(n)-1(v)30(o)-1(l)13(v)8(e)20(d)]TJ
+ET
+93.6 249.2 0.48 -12.72 re
+f*
+529.92 249.2 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 226.342 Tm
+0.236 Tw
+[(i)13(ndi)13(c)8(a)20(tes)8( )44(th)20(at )22(i)34(n)-1(for)15(m)15(a)20(ti)13(o)20(n)-1( )22(c)8(a)-1(m)37(pai)34(gns)30( )22(or)15( )44(gui)13(d)20(e)-1(l)13(i)13(n)20(es)8( m)15(a)-1(y)30( b)20(e)-1( v)30(a)-1(l)13(u)20(abl)13(e)20( to)20( e)20(n)-1(s)8(u)-1(r)37(e)-1( t)25(hat)]TJ
+ET
+93.6 236.48 0.48 -12.72 re
+f*
+529.92 236.48 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 213.622 Tm
+-0.003 Tw
+[(i)13(ndi)13(v)8(i)13(d)20(ual)13(s)8(\222)13( pr)15(ef)25(er)15(e)20(n)-1(c)8(e)-1(s)8( ar)15(e)20( )-21(b)20(a)-1(s)8(e)20(d )-21(o)20(n)-1( ful)13(l)13( )-21(i)13(n)20(for)15(m)15(a)-1(ti)13(o)20(n)20(.)3( )-21( Bet)25(t)3(er)15( )-21(i)13(n)20(for)15(m)15(a)20(ti)13(on)20( )-21(m)15(a)-1(y)8( )-21(l)34(e)-1(a)20(d)-1( )-21(t)25(o)-1( )-21(a)]TJ
+ET
+93.6 223.76 0.48 -12.72 re
+f*
+529.92 223.76 0.48 -12.72 re
+f*
+BT
+11.04 0 0 11.04 99.36 200.662 Tm
+[(dec)8(r)15(e)20(as)30(e i)13(n)-1( )22(th)20(e pr)37(op)20(ens)8(i)13(t)25(y)8( o)20(f)3( p)20(e)-1(o)20(p)-1(l)13(e)20( to)20( c)8(o)20(nti)13(n)20(ual)13(l)13(y)8( )22(op)20(po)20(s)8(e)-1( r)37(e)-1(s)8(o)20(ur)15(c)8(e)-1( c)30(o)-1(n)20(s)8(e)20(n)-1(ts)8(.)]TJ
+ET
+93.6 197.36 0.48 -0.48 re
+f*
+93.6 197.36 0.48 -0.48 re
+f*
+94.08 197.36 435.84 -0.48 re
+f*
+529.92 197.36 0.48 -0.48 re
+f*
+529.92 197.36 0.48 -0.48 re
+f*
+93.6 211.04 0.48 -13.68 re
+f*
+529.92 211.04 0.48 -13.68 re
+f*
+endstream endobj 185 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F7 127 0 R /F11 129 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 186 0 obj << /Length 7013 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(25)Tj
+/F3 1 Tf
+-34.32 57.54 TD
+0.005 Tc
+-0.003 Tw
+[(The )20(Fr)14(am)14(ewor)14(k: P)12(o)-4(li)23(tical D)7(e)21(cisi)23(on M)18(akin)16(g)-4( a)21(nd C)27(o)-4(st B)7(e)21(ar)14(ing)]TJ
+0 -2.18 TD
+0.008 Tc
+0.034 Tw
+[(Fi)6(gur)17(e 3)]TJ
+/F5 1 Tf
+3.96 0 TD
+0.003 Tc
+0.079 Tw
+[( )20(offe)19(rs a fr)16(amew)5(o)19(r)-4(k that)21( summ)16(ari)5(s)3(es t)21(he key p)19(o)-1(i)5(n)-1(ts fr)16(om th)19(e previ)5(o)19(us)]TJ
+-3.96 -1.16 TD
+0.239 Tw
+[(di)5(scussi)5(on. )20( )20(T)14(he )20(fr)16(amew)5(o)19(r)-4(k )20(can b)19(e)-1( used i)25(n)-1( tw)5(o basi)5(c)3( w)25(a)-1(ys: to u)19(nderst)21(and)]TJ
+T*
+0.004 Tc
+0.258 Tw
+[(probl)6(ems)24( i)6(n)0( cur)17(r)-3(ent g)20(o)0(vern)20(ment s)24(t)2(ructu)20(r)-3(es, a)20(nd to )20(predi)6(ct t)22(he )-20(be)20(nefi)6(t)2(s )-20(an)20(d)]TJ
+T*
+0.002 Tc
+0 Tw
+[(dr)-5(awbacks o)18(f)0( options)22( for)-5( )20(r)-5(e)-2(fo)18(r)-5(m)-5(.)]TJ
+/F3 1 Tf
+0 -2.82 TD
+0.005 Tc
+-0.003 Tw
+[(Figur)14(e )20(3: D)7(e)1(v)21(o)-4(lu)16(tio)16(n)-4( an)16(d P)12(o)-4(li)23(tical D)27(ecisi)23(on M)18(akin)16(g)]TJ
+ET
+0 0 0 RG
+0 J 0 j 2.16 w 10 M []0 d
+1 i
+402.96 501.44 57.6 -21.6 re
+S
+BT
+/F5 1 Tf
+12 0 0 12 409.92 488 Tm
+0.004 Tc
+[(B)-9(enefi)6(t)2(s)]TJ
+ET
+1 J 1 j
+453.36 537.44 m
+438.96 501.44 l
+S
+BT
+12 0 0 12 108.72 510.8 Tm
+-0.001 Tc
+[(P)-14(o)-5(litica)-5(l)]TJ
+0 -1.18 TD
+0.001 Tc
+(Decision)Tj
+ET
+0.72 w
+165 505.28 m
+165 505.28 l
+165 519.124 150.539 530.36 132.72 530.36 c
+114.901 530.36 100.44 519.124 100.44 505.28 c
+100.44 491.436 114.901 480.2 132.72 480.2 c
+150.539 480.2 165 491.436 165 505.28 c
+h
+165.36 494.24 m
+402.96 494.24 l
+S
+BT
+9.84 0 0 9.84 202.32 497.95 Tm
+0.006 Tc
+0.009 Tw
+[(Dec)-6(i)8(s)-6(i)8(ons)-6( ref)16(l)8(ec)-6(t)-9( )25(s)-6(o)1(c)-6(i)8(al)8( pref)16(erenc)-6(es)]TJ
+12 0 0 12 245.52 381.2 Tm
+-0.001 Tc
+[(Co)-5(st)]TJ
+T*
+0.004 Tc
+[(B)-9(ear)17(i)6(n)]TJ
+ET
+q
+245.52 365.6 48.48 26.88 re
+W n
+BT
+12 0 0 12 280.322 367.04 Tm
+0 Tc
+0 Tw
+(g)Tj
+ET
+Q
+301.8 375.68 m
+301.8 375.68 l
+301.8 389.524 285.726 400.76 265.92 400.76 c
+246.114 400.76 230.04 389.524 230.04 375.68 c
+230.04 361.836 246.114 350.6 265.92 350.6 c
+285.726 350.6 301.8 361.836 301.8 375.68 c
+h
+251.76 400.64 m
+165.36 487.04 l
+S
+BT
+9.84 0 0 9.84 108.72 454.75 Tm
+0.002 Tc
+[(A)-14(c)-10(c)-10(ount)12(abilit)-13(y)]TJ
+0 -1.2195 TD
+0.006 Tc
+-0.016 Tw
+[(t)-9(o)1( t)-9(a)1(x)-6( pay)-6(ers)]TJ
+2.9268 -2.439 TD
+0.473 Tw
+[(A)-11(v)-7(oi)7(d \223unf)-10(unded)]TJ
+0 -1.2195 TD
+[(m)-16(andat)15(es)-7(\224)]TJ
+ET
+410.16 479.84 m
+294.96 393.44 l
+S
+BT
+9.84 0 0 9.84 372.48 433.15 Tm
+-0.016 Tw
+[(Hori)8(z)-6(ont)-9(al)8( E)-10(qui)8(t)16(y)]TJ
+-17.2927 5.122 TD
+[(A)-10(v)-6(oi)8(d i)8(n)1(t)-9(e)1(rj)8(uri)8(s)-6(di)8(c)-6(t)16(i)8(onal)8( )-25(ex)-6(t)16(e)1(rnal)8(i)8(t)-9(i)8(e)1(s)]TJ
+ET
+0 J 0 j 2.16 w
+417.36 573.44 79.2 -36 re
+S
+BT
+12 0 0 12 429.12 560 Tm
+0.002 Tc
+[(S)-11(ubj)4(ecti)4(ve)]TJ
+-0.16 -1.16 TD
+-0.001 Tc
+[(in)-5(fo)-5(r)-8(m)12(a)-5(t)-3(io)-5(n)]TJ
+ET
+302.16 602.24 72 -50.4 re
+S
+BT
+12 0 0 12 312.96 588.8 Tm
+0 Tc
+[(Ob)-4(je)-4(ctive)]TJ
+-0.42 -1.16 TD
+0.003 Tc
+[(Inform)16(ation)]TJ
+0.38 -1.18 TD
+0.001 Tc
+0.001 Tw
+[(and S)-12(k)1(ills)]TJ
+ET
+1 J 1 j 0.96 w
+158.16 515.84 m
+302.16 573.44 l
+S
+BT
+9.84 0 0 9.84 159.12 562.75 Tm
+0.005 Tc
+-0.015 Tw
+[(I)-10(n)0(f)15(o)0(rm)-16(ed dec)-7(i)7(s)-7(i)7(on )-25(m)9(a)0(k)-7(i)7(ng)]TJ
+ET
+99.36 603.92 0.72 -0.72 re
+f*
+99.36 603.92 0.72 -0.72 re
+f*
+100.08 603.92 404.64 -0.72 re
+f*
+504.72 603.92 0.72 -0.72 re
+f*
+504.72 603.92 0.72 -0.72 re
+f*
+99.36 603.2 0.72 -253.44 re
+f*
+504.72 603.2 0.72 -253.44 re
+f*
+99.36 349.76 0.72 -0.72 re
+f*
+99.36 349.76 0.72 -0.72 re
+f*
+100.08 349.76 404.64 -0.72 re
+f*
+504.72 349.76 0.72 -0.72 re
+f*
+504.72 349.76 0.72 -0.72 re
+f*
+BT
+10.08 0 0 10.08 99.36 323.725 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 324.08 Tm
+0.003 Tc
+0.259 Tw
+[(The box)23(es on t)21(he ri)5(gh)19(t rep)19(r)-4(esen)19(t factual)5( c)23(harac)23(teri)5(sti)5(cs a)19(bout )-20(th)19(e )-20(i)5(ssue )-20(of)]TJ
+0 -1.16 TD
+0.004 Tc
+0.218 Tw
+[(concern )40(- )20(thei)26(r )20(l)6(o)0(cati)6(ons )20(are )20(gi)6(ven. )20(The ov)24(al)6( bubbl)6(es)24( on th)20(e l)6(e)0(ft r)17(epres)24(ent)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(deci)5(s)3(i)5(ons to b)19(e)-1( )-20(mad)19(e)-1( )-20(- )-20(th)19(ei)5(r )-20(l)5(o)-1(cati)25(ons )-20(ar)16(e )-20(choi)5(ces )-20(t)21(hat )-20(w)5(e)-1( must )-20(m)16(a)-1(ke. )-20( Matches)]TJ
+T*
+0.239 Tw
+[(betw)5(een )20(th)19(e )20(l)5(o)-1(cati)5(on)19( )20(of box)23(es or )20(bubbl)5(es i)25(ndi)5(cate el)25(ements)23( of effi)5(ci)5(e)19(n)-1(cy i)5(n)]TJ
+T*
+0.059 Tw
+[(soci)5(al)5( )20(deci)5(s)3(i)5(on m)16(a)-1(ki)5(ng. )20(Mi)5(smatch)19(es rep)19(r)-4(esent)21( pro)19(b)-1(l)5(e)-1(ms th)19(at ar)16(e l)5(i)5(k)3(el)5(y to a)19(r)-4(i)5(s)3(e)]TJ
+0 -1.14 TD
+0 Tw
+[(and nee)18(d to be)18( add)18(r)-5(e)-2(ssed. We\222ll us)22(e the )20(exam)-5(ple)18( of )-20(sub)18(d)-2(ivision )-20(to )-20(illust)20(r)-5(a)-2(te )-20(t)20(h)-2(e)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(w)5(a)-1(y the di)5(ag)19(ram w)5(o)19(rks.)]TJ
+12 0 2.551 12 99.36 212.96 Tm
+[(Il)5(l)5(u)-1(strati)5(on: S)10(o)-1(ci)5(al)5( c)23(hoi)5(ces a)19(bout S)10(ubdi)5(vi)5(si)5(o)19(n)-1( and )20(Local)5( La)19(nd U)5(s)3(e)]TJ
+12 0 0 12 99.36 185.36 Tm
+0.259 Tw
+[(To anal)5(yse)19( a pa)19(rti)5(c)3(ul)5(ar i)5(s)3(s)23(ue, w)5(e)-1( fi)25(rst nee)19(d to )-20(i)5(d)-1(e)19(n)-1(ti)5(fy )-20(the )-20(c)23(o)-1(mm)16(uni)5(ty )-20(that)]TJ
+T*
+0.039 Tw
+[(di)5(rectl)5(y)3( ben)19(efi)5(t)1(s fro)19(m)-4( re)19(gul)5(ati)5(o)-1(n)19(.)1( In th)19(e case )-20(of)21( )-20(the )-20(s)23(ubdi)5(vi)5(si)5(on )-20(q)19(uesti)5(on, )-20(t)21(h)-1(i)5(s)3( )-20(i)5(s)]TJ
+T*
+0.004 Tc
+0.218 Tw
+[(the ow)6(ners)24( of th)20(e l)6(and t)22(hat bo)20(rders)24( the p)20(r)-3(opose)20(d)0( sub)20(d)0(i)6(v)4(i)6(s)4(i)6(on and the )-20(l)6(o)0(cal)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(nei)5(ghbou)19(rhoo)19(d, and )20(to a l)5(e)-1(sse)19(r exte)19(nt the ci)5(ty w)25(here)19( the su)19(bdi)5(vi)5(si)5(on )-20(i)5(s)3( )-20(l)5(o)-1(cat)21(ed.)]TJ
+T*
+0.04 Tw
+[(T)-7(he pe)18(ople in t)20(hese a)18(r)-5(eas will have)18( unobs)22(er)-5(vable)18( subjective )20(pr)-5(efe)18(r)-5(ences)22( )-20(about)]TJ
+0 -1.14 TD
+0.259 Tw
+[(the val)5(ue o)19(f)1( the b)19(enefi)5(t)1(s )20(of the )20(regul)5(ati)25(on. P)10(eopl)5(e c)23(a)-1(re )20(about t)21(he )-20(physi)5(c)23(a)-1(l)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(effects and)19( have vi)5(ew)5(s )20(about )20(the ap)19(prop)19(ri)5(ate d)19(e)-1(fi)5(ni)5(ti)5(on )20(of pro)19(perty )20(ri)5(ghts. )20( )-20(S)10(o)-1(me)]TJ
+T*
+0.139 Tw
+[(peopl)5(e bel)5(i)5(e)-1(v)23(e)-1( com)16(m)-4(uni)5(ti)5(es )20(have si)5(gni)5(fi)5(ca)19(nt ri)5(g)19(h)-1(ts to co)19(ntrol)5( )-20(p)19(r)-4(i)5(v)3(ate )-20(l)5(a)19(nd )-20(use)]TJ
+ET
+endstream endobj 187 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 188 0 obj << /Type /Page /Parent 176 0 R /Resources 190 0 R /Contents 189 0 R >> endobj 189 0 obj << /Length 9266 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(26)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.179 Tw
+[(because i)5(t)1( a)19(ffects th)19(e com)16(m)-4(uni)5(ty as )20(a w)5(hol)5(e, w)5(h)19(ereas)23( )-20(othe)19(rs )-20(bel)5(i)5(e)-1(ve )-20(i)25(n)-1( )-20(the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.078 Tw
+[(predo)20(mi)6(nance )20(of pri)6(v)4(a)20(t)2(e pr)17(operty)24( ri)6(ghts.)22( Fo)20(r i)6(ssues suc)24(h)0( as )-20(sub)20(d)0(i)6(v)4(i)6(s)4(i)6(on )-20(thes)24(e)]TJ
+T*
+0.058 Tw
+[(prefer)17(ences a)20(r)-3(e cri)6(t)2(i)6(c)4(al)6( i)26(n)0(for)17(m)-3(ati)6(on f)22(o)0(r g)20(ood deci)6(s)4(i)6(o)20(n maki)6(n)20(g)0(. F)15(o)0(r )-20(ot)22(her )-20(i)6(ssu)20(es)]TJ
+T*
+-0.016 Tc
+0.018 Tw
+[(t)-18(h)-20(e)-20(y)-16( m)-23(a)-20(y)-16( be)-20( l)-14(e)-20(s)-16(s)-16( i)-14(m)-23(po)-20(r)-23(t)-18(an)-20(t)-18(.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.038 Tw
+[(The )20(oth)20(e)0(r )20(ch)20(aracte)20(ri)6(sti)6(c)4( )20(w)6(e)0( ne)20(ed to )20(deter)17(mi)6(ne i)6(s)4( th)20(e l)6(o)0(cati)6(o)20(n)0( and i)26(m)-3(port)22(ance o)20(f)]TJ
+0 -1.16 TD
+0.003 Tc
+0.479 Tw
+[(observabl)5(e)19(,)1( )20(obj)5(ecti)5(ve)19( )20(i)5(n)-1(for)16(m)-4(ati)5(on. )40( )20(In th)19(e case of)21( subdi)5(vi)5(si)5(on, )20(obj)5(ecti)5(ve)]TJ
+T*
+0.039 Tw
+[(i)5(n)-1(formati)25(on, such )20(as know)5(l)5(e)-1(d)19(ge ab)19(out r)16(oad desi)25(gn, si)5(l)5(t)1(ati)5(o)-1(n)19( pro)19(b)-1(l)5(e)-1(ms, d)19(r)-4(ai)5(na)19(ge)]TJ
+T*
+0.159 Tw
+[(and )20(so )20(on)19(, )20(i)5(s)3( )20(avai)5(l)5(abl)5(e )20(l)25(o)-1(cal)5(l)5(y)3( )20(beca)19(u)-1(se of l)5(o)-1(c)23(a)-1(l)5( expe)19(ri)5(ence b)19(u)-1(t al)5(so co)19(ul)5(d be)]TJ
+0 -1.24 TD
+0.019 Tw
+[(gai)5(ned at )20(the na)19(ti)5(onal)5( )-20(l)5(e)-1(vel)5(.)]TJ
+10.08 0 0 10.08 246.72 623.005 Tm
+-0.008 Tc
+(11)Tj
+12 0 0 12 257.76 620 Tm
+0.002 Tc
+0.04 Tw
+[( In any)22( case, fo)18(r this issu)18(e the c)22(r)-5(itical info)18(rmatio)18(n)]TJ
+-13.2 -1.16 TD
+-0.001 Tw
+[(i)5(s)3( the l)5(o)-1(cal)5( pe)19(opl)5(e\222)5(s pr)16(efer)16(ences ab)19(out th)19(e natu)19(r)-4(e of )20(the co)19(mmuni)5(ty)23( they l)5(i)5(v)3(e i)5(n)-1(.)]TJ
+0 -2.32 TD
+0.119 Tw
+[(Once w)5(e)-1( have)19( establ)5(i)5(s)3(he)19(d the )20(natur)16(e and)19( l)5(o)-1(cati)5(on )20(of the fi)5(x)23(ed asp)19(e)-1(cts of )-20(th)19(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.258 Tw
+[(subdi)6(vi)6(si)6(on i)6(ssue w)6(e)0( c)24(an tu)20(rn ou)20(r atte)20(nti)6(on to)20( the va)20(ri)6(abl)6(e el)26(ements)24(.)2( )-20(Th)20(e)]TJ
+0 -1.16 TD
+0.003 Tc
+0.079 Tw
+[(bubbl)5(es )20(i)5(ndi)5(ca)19(te )20(the )20(\221)5(l)5(o)-1(c)23(a)-1(ti)5(on\222)5( )20(of)21( pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(o)19(n-m)16(a)-1(ki)5(ng an)19(d cost be)19(ari)5(ng.)21( In)]TJ
+T*
+0.119 Tw
+[(the case of)21( subdi)5(vi)5(si)5(on )20(unde)19(r the R)25(M)-4(A)10(,)1( both po)19(l)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(ons )20(and costs)23( )-20(are)]TJ
+T*
+0.079 Tw
+[(l)5(o)-1(cal)5(.)1( Gi)5(ven th)19(at ben)19(efi)5(t)1(s ar)16(e l)5(o)-1(cal)5(,)1( an)19(d subj)5(ecti)5(v)23(e)-1( i)5(n)-1(for)16(m)-4(ati)5(on )-20(i)5(s)23( )-20(mor)16(e)-1( )-20(di)5(ffi)5(cul)5(t)]TJ
+0 -1.24 TD
+-0.001 Tw
+[(to obtai)5(n t)21(han o)19(b)-1(j)5(e)-1(cti)5(v)3(e fo)19(r thi)5(s)3( i)5(ssue,)21( the i)5(n)-1(sti)5(t)1(u)19(t)1(i)5(onal)5( st)21(ructu)19(r)-4(e i)5(s)3( w)5(e)-1(l)5(l)5( al)5(i)5(g)-1(n)19(ed.)]TJ
+10.08 0 0 10.08 511.44 510.925 Tm
+-0.008 Tc
+(12)Tj
+12 0 0 12 99.36 480.08 Tm
+0.003 Tc
+0.119 Tw
+[(Matches o)19(r)-4( l)5(i)5(n)-1(ks betw)25(een th)19(e l)5(o)-1(ci)5(, box)23(es and b)19(ubbl)5(es,)21( bri)5(ng )-20(i)25(m)-4(pr)16(ovemen)19(ts )-20(i)5(n)]TJ
+0 -1.16 TD
+0.24 Tw
+[(the )20(effi)4(ci)4(ency )20(of soci)4(al)4( de)18(ci)4(si)4(on maki)4(n)18(g)-2(. In )20(the case)18( of sub)18(d)-2(i)4(v)2(i)4(s)2(i)4(on, w)4(h)-2(e)18(r)-5(e)]TJ
+0 -1.14 TD
+0.32 Tw
+[(benefits, costs)22( and d)18(e)-2(cisions m)15(a)-2(tch, p)18(r)-5(efe)18(r)-5(ences will be r)-5(e)-2(p)18(r)-5(esent)20(ed, )-20(an)18(d)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.183 Tw
+[(d)-5(e)-5(c)-1(isio)-5(n)-5( m)-8(a)-5(kin)15(g)-5( will b)-5(e)-5( r)12(e)-5(la)-5(tive)-5(ly )-20(b)-5(a)-5(l)1(a)15(n)-5(ce)-5(d)-5(.)-3( )-20( T)-10(h)-5(e)-5(r)12(e)-5( )-20(a)-5(r)12(e)-5( )-20(fe)-5(w )-20(in)-5(te)15(r)-8(j)1(u)-5(r)-8(isd)-5(i)1(ctio)15(n)-5(a)-5(l)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(external)5(i)5(t)1(i)5(e)-1(s,)21( and t)21(he nei)5(g)19(hbou)19(rhood )20(bears)23( al)5(l)5( costs. )-20(If)21( )-20(ci)5(ti)5(zens )-20(thi)5(n)-1(k)23( )-20(deci)5(s)3(i)5(ons)]TJ
+T*
+0.019 Tw
+[(are poo)19(r, th)19(ey can vot)21(e)-1( agai)25(nst counci)5(l)5( )20(membe)19(r)-4(s o)19(r)-4( be )20(more )20(di)5(rectl)5(y)3( )-20(i)5(n)-1(v)23(o)-1(l)5(v)3(ed )-20(i)5(n)]TJ
+T*
+-0.001 Tw
+[(i)5(n)-1(fl)5(uenci)5(ng l)5(o)-1(cal)5( )20(pol)5(i)5(cy.)]TJ
+0 -2.3 TD
+0 Tc
+0.022 Tw
+[(It is p)-4(o)-4(ssib)-4(l)2(e)-4( th)16(a)-4(t)-2( th)-4(e)-4( ju)16(r)-7(i)2(sd)-4(ictio)-4(n)-4( f)18(o)-4(r)-7( su)16(b)-4(d)-4(i)2(visio)-4(n)-4( is )-20(still )-20(to)-4(o)16( )-20(la)-4(r)-7(g)-4(e)-4( a)-4(l)2(th)-4(o)-4(u)16(g)-4(h)-4( )-20(p)-4(e)-4(o)16(p)-4(l)2(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.258 Tw
+[(through)20(out th)20(e Te)20(rri)6(to)20(ri)6(al)6( Local)6( A)11(u)0(t)22(hori)6(t)2(y )20(\(TLA)11(\) c)24(oul)6(d )-20(be argu)20(ed )-20(to have )-20(a)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(l)5(egi)5(ti)5(mate )20(i)5(n)-1(t)21(e)-1(rest. )20( R)5(e)-1(l)5(a)-1(ti)5(vel)5(y)3( uni)25(nteres)23(ted par)16(ti)5(es m)16(a)-1(y seek t)21(o)-1( i)5(m)-4(pos)23(e thei)5(r)]TJ
+T*
+0 Tc
+0.322 Tw
+[(p)-4(r)-7(e)-4(f)-2(e)-4(r)13(e)-4(n)-4(c)0(e)-4(s)0( )20(o)16(n)-4( )20(th)-4(o)-4(s)0(e)-4( )40(d)-4(i)2(r)-7(e)-4(ctly )20(a)16(ffe)-4(cte)-4(d)-4(.)18( Id)-4(e)-4(a)-4(lly, i)22(n)-4( th)-4(is ca)-4(se)-4(,)18( th)-4(e)-4( )20(T)-9(L)-4(A will)]TJ
+0 -1.14 TD
+0.002 Tc
+0.12 Tw
+[(pr)-5(im)-5(ar)-5(ily )20(ac)22(t )20(as )20(a f)20(a)-2(cilitator)-5( )20(for)-5( n)18(e)-2(ighbo)18(ur)-5(hoo)18(d decision)18(-)-5(m)-5(a)-2(kin)18(g)-2( on issu)18(es with)]TJ
+0 -1.16 TD
+0.179 Tw
+[(very )20(smal)5(l)5( )20(ext)21(e)-1(rnal)5(i)5(t)1(y )40(bound)19(ari)5(e)-1(s )20(suc)23(h)-1( )20(as fe)19(nces, ho)19(use col)5(o)-1(u)19(r)-4( an)19(d di)5(stance)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(from b)20(ounda)20(ry.)]TJ
+0 -2.32 TD
+0.118 Tw
+[(The di)6(ag)20(ram)17( onl)6(y capt)22(ures tw)26(o of th)20(e thr)17(ee cri)6(t)2(e)20(r)-3(i)6(a)0( fo)20(r goo)20(d deci)6(s)4(i)6(on maki)6(ng.)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(One re)19(mai)5(n)-1(i)5(ng i)5(ssu)19(e that )20(must b)19(e)-1( consi)5(d)-1(e)19(r)-4(ed i)5(s)3( w)5(h)19(ether)16( the cos)23(t)1(s of )-20(du)19(pl)5(i)5(c)3(ati)5(n)-1(g)]TJ
+0 -1.16 TD
+0.079 Tw
+[(obj)5(ecti)5(ve i)5(n)-1(fo)19(rmati)5(o)19(n)-1( outw)5(e)-1(i)5(g)19(h the )20(benefi)5(t)1(s t)21(hat a)19(r)-4(i)5(s)3(e th)19(rough l)25(o)-1(cal)5( cont)21(rol)5( )-20(of )-20(a)]TJ
+T*
+0.059 Tw
+[(l)5(o)-1(cal)5( i)5(ssue. In t)21(h)-1(i)5(s)3( case t)21(hey )-20(don\222)5(t)21(.)1( )-20( )-20(S)10(ubj)5(ecti)5(ve )-20(p)19(r)-4(efe)19(r)-4(ences are )-20(ve)19(ry )-20(i)5(m)-4(p)19(o)-1(rtan)19(t)]TJ
+0 -1.56 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 201.92 m
+99.366 201.92 l
+S
+BT
+12 0 0 12 200.16 197.84 Tm
+( )Tj
+ET
+243.843 201.92 m
+200.163 201.92 l
+S
+BT
+10.08 0 0 10.08 99.36 186.205 Tm
+-0.008 Tc
+(11)Tj
+1.0952 -0.3095 TD
+0.111 Tw
+[( )-1333(A)-8( )24(c)-8(ont)-16(r)-8(a)0(s)-8(t)-16(ing )24(ex)-8(am)-8(ple )24(would )24(be dec)-8(iding appr)-8(opr)-8(iat)-16(e lev)-8(els)-8( of)-16( dr)-8(ink)-8(ing wat)-16(er)-8( t)-16(r)-8(eat)8(m)-8(ent)-16(.)]TJ
+1.7143 -1.1667 TD
+-0.005 Tc
+0.322 Tw
+[(Here knowledge about)-13( t)-13(he cost)-13(s and physical ef)11(f)-13(e)3(ct)-13(s)19( of)-13( )-24(di)26(f)-13(f)-13(e)3(rent)-13( syst)-13(e)27(ms )-24(is more)]TJ
+0 -1.1429 TD
+-0.008 Tc
+0.182 Tw
+[(im)-8(por)-8(t)-16(ant)-16( t)-16(han v)-8(a)0(r)-8(ianc)-8(e in pr)-8(ef)-16(er)-8(enc)-8(es)16( about)-16( wat)-16(er)-8( qualit)-16(y)-8(.)8( P)16(r)-8(ef)-16(er)-8(enc)-8(es)-8( )-24(ar)-8(e )-24(pr)-8(obably)]TJ
+0 -1.1667 TD
+0.016 Tw
+[(f)-16(air)-8(ly)-8( hom)-8(ogeneous)-8(.)]TJ
+-2.8095 -2.2381 TD
+(12)Tj
+1.0952 -0.3095 TD
+0.23 Tw
+[( )-1214(I)-16(n)0( t)-16(he c)-8(a)0(s)-8(e)24( of)-16( dr)-8(ink)-8(ing wat)-16(er)-8( qualit)-16(y)-8(,)8( benef)-16(it)-16(s)-8( ar)-8(e)24( at)-16( t)-16(he )-24(r)-8(egional )-24(lev)-8(el )-24(and )-24(objec)-8(t)-16(i)0(v)-8(e)]TJ
+1.7143 -1.1905 TD
+0.111 Tw
+[(inf)-16(or)-8(m)-8(a)0(t)-16(ion is)-8( c)-8(r)-8(i)0(t)-16(i)0(c)-8(al.)8( Under)-8( t)-16(he R)23(M)-8(A)-8(,)8( r)-8(egional c)-8(ounc)-8(ils)-8( m)-8(a)0(k)-8(e)0( dec)-8(is)-8(ions)-8( )-24(about)-16( )-24(dr)-8(ink)-8(ing)]TJ
+0 -1.1429 TD
+0.135 Tw
+[(wat)-16(er)-8( pr)-8(ov)-8(is)-8(ion.)-16( Regional c)-8(ounc)-8(il boundar)-8(ies)-8( r)-8(oughly)-8( m)-8(a)0(t)-16(c)-8(h wat)-16(er)-8(s)-8(heds)-8(.)-16( )-24( W)-17(a)0(t)-16(e)0(r)15( )-24(us)-8(er)-8(s)]TJ
+T*
+0.016 Tw
+[(and r)-8(a)0(t)-16(epay)-8(er)-8(s)-8( bear)-8( c)-8(o)0(s)-8(t)-16(s)16(.)-16( )24( A)-8(gain,)-16( dec)-8(is)-8(ions)-8(,)-16( benef)-16(it)-16(s)16( and c)-8(o)0(s)-8(t)-16(s)16( ar)-8(e aligned.)]TJ
+ET
+endstream endobj 190 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 191 0 obj << /Length 7859 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(27)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.399 Tw
+[(and l)5(i)5(k)3(el)5(y to b)19(e)-1( extr)16(emel)5(y h)19(e)-1(tero)19(geneo)19(us, so a)19(n)-1(y advan)19(tage )-20(o)19(f)1( )-20(l)5(a)-1(ck )-20(of)]TJ
+0 -1.16 TD
+0.004 Tc
+0.018 Tw
+[(dupl)6(i)6(c)4(ati)6(on )20(th)20(roug)20(h )20(one )20(deci)6(s)4(i)6(on b)20(e)0(i)6(ng m)17(ade cen)20(t)2(ral)6(l)6(y)4( i)6(s)4( l)6(i)6(k)4(el)6(y to)20( be ou)20(tw)6(ei)6(ghed)]TJ
+T*
+0.003 Tc
+0.419 Tw
+[(by the adv)23(antages)23( of m)16(a)-1(xi)5(mi)5(si)5(ng p)19(r)-4(efe)19(r)-4(ence )20(revel)5(a)-1(ti)5(o)19(n)-1( thr)16(ough l)5(o)-1(c)23(a)-1(l)5(i)5(s)3(ed)]TJ
+T*
+-0.001 Tw
+[(deci)5(s)3(i)5(on maki)5(n)19(g)-1(.)]TJ
+/F3 1 Tf
+0 -2.58 TD
+0.008 Tc
+-0.006 Tw
+[(Mobi)6(l)26(i)6(ty a)24(nd D)30(evol)26(u)-1(ti)26(on)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.002 Tc
+0.18 Tw
+[(M)-5(obility )20(has so)18(m)-5(e)-2( positiv)22(e effects)22( on th)18(e efficiency )20(of public )20(good p)18(r)-5(ovision.)]TJ
+0 -1.16 TD
+0.004 Tc
+0.518 Tw
+[(W)8(hen ther)17(e are)20( mul)6(t)2(i)6(p)0(l)6(e)0( j)26(u)0(ri)6(sdi)6(c)4(ti)6(ons )20(offeri)26(ng a r)17(ange )20(of )-20(packa)20(ges )-20(of)]TJ
+T*
+0.002 Tc
+0.06 Tw
+[(taxation/r)15(egulatio)18(n and )20(public ser)-5(v)2(ic)22(es, a pseu)18(do m)-5(a)-2(r)-5(k)2(et)20( )-20(em)-5(e)18(r)-5(ges. )-20( )-20(P)9(e)-2(o)18(p)-2(le )-20(will)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(reveal)6( thei)26(r pr)17(efere)20(n)0(ces fo)20(r publ)6(i)6(c)4( g)20(oods by)24( )-20(choosi)6(n)0(g)20( )-20(the )-20(j)6(u)20(ri)6(sdi)6(c)4(ti)6(on )-20(i)6(n)0( )-20(w)6(h)0(i)6(c)24(h)]TJ
+0 -1.14 TD
+0.258 Tw
+[(they l)6(i)6(v)4(e. M)17(o)0(re j)6(u)20(ri)6(sdi)6(c)4(ti)6(ons i)6(m)17(pl)6(y gre)20(a)0(ter c)24(hoi)6(ce an)20(d )-20(mo)20(re )-20(com)17(peti)6(t)2(i)6(on to)]TJ
+0 -1.16 TD
+0.003 Tc
+0.059 Tw
+[(provi)5(de b)19(o)-1(th th)19(e packag)19(e)-1(s peo)19(pl)5(e pr)16(efer )20(and to )20(provi)5(d)19(e )-20(servi)5(c)3(es )-20(i)25(n)-1( )-20(an )-20(ef)21(fi)5(ci)5(ent)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(w)6(a)0(y. The )20(Ti)6(ebo)20(ut mo)20(del)6(, w)6(h)0(i)6(c)4(h fo)20(rmal)6(i)6(s)4(es)24( the o)20(perati)26(on of )-20(t)22(h)0(i)6(s)4( )-20(pseud)20(o )-20(ma)20(rket,)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(i)5(s)3( di)5(scussed i)5(n)-1( m)16(o)-1(re d)19(e)-1(tai)5(l)5( i)5(n)-1( A)10(ppe)19(ndi)5(x Th)19(ree.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.058 Tw
+[(N)6(e)0(w)6( )20(Zeal)6(an)20(ders )20(a)20(r)-3(e )20(a )40(rel)6(a)0(ti)6(vel)6(y)4( )20(mobi)6(l)6(e)0( p)20(eopl)6(e. B)11(e)0(tw)6(e)20(en 19)20(91 and)20( 1996,)22( 24%)]TJ
+0 -1.16 TD
+0.078 Tw
+[(of N)6(e)0(w)6( Zeal)26(anders)24( chose )20(a new)6( j)6(u)0(ri)6(s)24(d)0(i)6(c)4(ti)6(on to l)6(i)6(v)4(e)20( i)6(n)0(. D)6(i)6(ffe)20(rent )20(TLA)11(s)4( do )-20(hav)24(e)]TJ
+T*
+0.003 Tc
+0.139 Tw
+[(di)5(fferent )40(\223cul)5(tu)19(res\224 t)21(o)-1( a ce)19(rtai)5(n ext)21(ent, e.)21(g.: W)7(a)-1(i)5(t)1(ake)19(r)-4(e C)5(i)5(t)1(y an)19(d Man)19(u)-1(kau C)5(i)5(t)1(y)]TJ
+T*
+0.039 Tw
+[(have very )20(di)5(ffere)19(nt cha)19(r)-4(acte)19(rs, so pe)19(opl)5(e have)19( som)16(e)-1( )-20(choi)5(ce. )-20( )-20(A)10(l)5(th)19(ough )-20(l)5(o)-1(c)23(a)-1(ti)5(on)]TJ
+T*
+0.16 Tw
+[(decisions )20(ar)15(e heavily d)18(epend)18(ent on j)24(ob op)18(por)-5(tu)18(nities, this )20(m)-5(obility still allows)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(some pr)16(efer)16(ence r)16(e)-1(vel)5(a)-1(ti)5(on )20(and p)19(u)-1(ts som)16(e)-1( press)23(u)-1(re o)19(n)-1( l)5(o)-1(cal)5( j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons.)]TJ
+0 -2.32 TD
+0.7 Tw
+[(M)-5(obility also ca)18(uses som)15(e)-2( significant)20( pr)-5(o)18(b)-2(lem)-5(s)2( with r)-5(egulati)24(on. )-20(A)9(n)-2(y)]TJ
+0 -1.16 TD
+0.004 Tc
+0.218 Tw
+[(i)6(n)0(terj)6(uri)6(s)4(di)6(cti)6(o)20(nal)6( )20(exte)20(rnal)6(i)6(t)2(i)6(e)0(s )20(a)20(r)-3(e )20(ex)24(acerb)20(a)0(ted w)6(h)0(e)20(n)0( peo)20(pl)6(e can )20(move aw)6(ay)]TJ
+T*
+0.003 Tc
+0.119 Tw
+[(from th)19(e are)19(a)-1(s bea)19(ri)5(ng cos)23(t)1(s and i)5(n)19(to the )20(areas)23( recei)5(v)3(i)5(n)19(g bene)19(fi)5(ts. D)5(e)-1(ci)5(si)5(on)19(-)]TJ
+0 -1.14 TD
+0.039 Tw
+[(maki)5(ng )20(i)5(s)3( )20(no)19(t )20(onl)5(y un)19(bal)5(ance)19(d)-1(, but c)23(an al)5(so l)5(e)-1(a)19(d)-1( to )20(unstabl)5(e c)23(o)-1(mm)16(uni)5(ti)5(es. W)7(e)]TJ
+0 -1.16 TD
+0.04 Tw
+[(pr)-5(obably )40(do )20(not)20( )20(want to )20(dir)-5(e)-2(ctly )20(r)-5(e)-2(str)-5(i)4(ct )20(m)-5(obility on)18( the b)18(a)-2(sis of th)18(ese pr)15(oblem)-5(s,)]TJ
+T*
+0.059 Tw
+[(but w)5(e)-1( do w)5(a)19(nt to b)19(e)-1( aw)5(ar)16(e of th)19(em )-20(to)19( )-20(unde)19(rstand)19( )-20(the )-20(d)19(e)-1(tri)5(m)-4(e)19(n)-1(tal)5( )-20(si)5(de effects)]TJ
+T*
+-0.001 Tw
+[(of certai)5(n )20(pol)5(i)5(c)3(i)5(e)-1(s.)]TJ
+0 -2.3 TD
+0 Tc
+0.282 Tw
+[(M)-7(o)-4(b)-4(ility lim)-7(its th)-4(e)16( a)-4(b)-4(ility o)-4(f)-2( lo)-4(c)20(a)-4(l g)-4(o)-4(v)0(e)16(r)-7(n)-4(m)-7(e)16(n)-4(ts to)-4( r)-7(e)-4(d)-4(i)2(str)-7(i)2(b)16(u)-4(te)-4( )-20(in)-4(co)16(m)-7(e)-4( )-20(e)-4(i)2(th)16(e)-4(r)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(di)5(rectl)5(y)3( or )20(thro)19(ugh se)19(rvi)5(c)3(es. A)10( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( that )20(redi)5(st)21(ri)5(butes f)21(r)-4(om )20(hi)5(gh i)5(n)-1(co)19(me to)]TJ
+T*
+0.12 Tw
+[(low )20(incom)-5(e)-2( will ten)18(d)-2( to lose )20(high-)-5(inc)22(o)-2(m)-5(e)-2( )20(people )20(and gai)24(n low-)-5(inco)18(m)-5(e)-2( pe)18(ople.)]TJ
+T*
+0.119 Tw
+[(A)10(s)3( they l)5(o)-1(se the )20(hi)5(gh i)5(n)-1(co)19(me, hi)5(g)19(h)-1( tax )-20(p)19(a)-1(yi)5(ng )-20(peo)19(pl)5(e )-20(th)19(ey )-20(beco)19(m)-4(e )-20(un)19(abl)5(e )-20(to)]TJ
+T*
+0.059 Tw
+[(support t)21(hei)5(r p)19(r)-4(evi)5(ous l)25(e)-1(vel)5( of se)19(rvi)5(c)3(e )-20(p)19(r)-4(ovi)5(s)3(i)5(on. )-20( )-20(It)21( )-20(al)5(so )-20(bec)23(omes more di)5(ffi)5(cul)5(t)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(to suppo)19(rt di)5(vers)23(e com)16(m)-4(uni)5(ti)5(es.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.198 Tw
+[(W)8(hen econo)20(mi)6(es of sc)24(al)6(e )-20(i)6(n)0( )-20(pu)20(bl)6(i)6(c)4( )-20(good provi)6(s)4(i)6(on exi)6(s)4(t, )-20(smal)6(l)6( )-20(c)24(o)0(mm)17(uni)6(ti)6(es)]TJ
+0 -1.16 TD
+0.003 Tc
+0.059 Tw
+[(may suffe)19(r fro)19(m)-4( out )20(mi)5(gra)19(t)1(i)5(on bec)23(ause of)21( )-20(tax )-20(exte)19(rnal)5(i)5(t)1(i)5(e)-1(s. )-20(A)10( )-20(perso)19(n )-20(l)5(eavi)5(ng a)]TJ
+T*
+0.199 Tw
+[(smal)5(l)5( comm)16(uni)5(ty l)5(o)-1(w)5(e)-1(rs)23( the cos)23(t)1( of pu)19(bl)5(i)5(c)3( servi)5(c)3(es )20(by l)5(e)-1(ss tha)19(n)-1( the )-20(l)5(o)-1(ss)23( )-20(of)]TJ
+0 -1.14 TD
+0.004 Tc
+0.018 Tw
+[(revenue.)22( )20( )20(Th)20(us )20(the )40(mi)6(gra)20(n)0(t i)6(m)-3(pos)24(es an ex)24(ternal)6(i)6(t)2(y )20(on th)20(e re)20(mai)6(n)0(i)6(ng co)20(mmu)20(ni)6(ty.)]TJ
+0 -1.16 TD
+0.058 Tw
+[(C)6(onversel)6(y)4(, w)6(h)20(ere di)6(sec)24(onomi)26(e)0(s of scal)6(e)20( ari)6(s)4(e )-20(i)6(n)0( )-20(l)26(a)0(rge )-20(c)24(o)0(mmu)20(ni)6(ti)6(es, )-20(a perso)20(n)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(enteri)5(ng )20(a l)5(a)-1(rg)19(e com)16(m)-4(uni)5(ty )20(may i)5(n)-1(cr)16(ease th)19(at com)16(m)-4(uni)5(ty\222)5(s)3( tax)23( take by l)25(e)-1(ss)]TJ
+T*
+-0.001 Tw
+[(than the c)23(o)-1(st of p)19(r)-4(ovi)5(d)-1(i)5(n)-1(g)19( addi)5(ti)5(on)19(al)5( )-20(servi)5(c)3(es.)21( )-20( )-20(Thi)5(s)3( probl)5(e)19(m)-4( )-20(coul)5(d)19( )-20(be )-20(ad)19(dresse)19(d)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(by maki)6(ng c)24(o)0(mmu)20(ni)6(ti)6(es mo)20(re si)6(mi)6(l)6(a)20(r i)6(n)0( si)6(ze )-20(t)22(o)0( )-20(make)20( )-20(best )-20(us)24(e )-20(of )-20(any)24( )-20(econo)20(mi)6(es)]TJ
+0 -1.14 TD
+0.003 Tc
+0.019 Tw
+[(of scal)5(e)-1( and)19( avoi)5(d di)5(sec)23(onomi)25(e)-1(s. A)10(l)5(tern)19(ati)5(v)3(el)5(y l)5(a)-1(rg)19(er )-20(co)19(mmuni)5(ti)25(es )-20(may )-20(w)5(a)19(nt )-20(to)]TJ
+ET
+endstream endobj 192 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 193 0 obj << /Type /Page /Parent 176 0 R /Resources 195 0 R /Contents 194 0 R >> endobj 194 0 obj << /Length 1319 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(28)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.059 Tw
+[(subsi)5(d)-1(i)5(s)3(e smal)5(l)5( co)19(mmu)19(ni)5(ti)5(es, or)16( tax new)5( )20(devel)5(op)19(ment i)5(n)-1( )-20(l)25(a)-1(rge )-20(ci)5(ti)25(es )-20(to )-20(p)19(r)-4(event)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(i)5(neffi)5(ci)5(ent mi)5(g)19(r)-4(ati)5(on )20(tow)5(a)-1(rd)19( overc)23(r)-4(ow)5(ded)19( ci)5(ti)5(es.)]TJ
+0 -2.32 TD
+-0.001 Tc
+0.123 Tw
+[(T)-10(h)-5(u)-5(s)-1( )20(m)12(o)-5(b)-5(ility )20(co)-5(m)-8(p)-5(l)21(e)-5(m)-8(e)-5(n)-5(t)-3(s)19( d)-5(e)-5(v)-1(o)-5(l)1(u)-5(t)-3(io)15(n)-5( b)-5(y)-1( im)12(p)-5(r)-8(o)-5(v)-1(in)-5(g)15( p)-5(r)-8(e)-5(f)17(e)-5(r)-8(e)-5(n)-5(c)19(e)-5( r)-8(e)-5(ve)-5(l)21(a)-5(tio)-5(n)-5(,)-3( b)15(u)-5(t)]TJ
+0 -1.14 TD
+0.004 Tc
+0.138 Tw
+[(al)6(so )20(makes )40(appro)20(p)0(ri)6(ate)20( handl)6(i)6(n)20(g of i)6(n)0(t)22(e)0(rj)6(uri)6(s)4(di)6(cti)26(onal)6( i)6(ssues )20(and r)17(edi)6(stri)6(b)20(u)0(ti)6(on)]TJ
+0 -1.16 TD
+0.003 Tc
+0.039 Tw
+[(cri)5(t)1(i)5(c)3(al)5(. Insti)5(t)1(uti)25(onal)5( str)16(u)-1(ctures)23( need )20(to take)19( i)5(n)-1(to )-20(acco)19(unt )-20(th)19(e )-20(dyna)19(mi)5(c )-20(i)5(m)-4(pact)21( )-20(of)]TJ
+T*
+-0.001 Tc
+[(m)-8(o)-5(b)-5(ility.)]TJ
+ET
+endstream endobj 195 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 196 0 obj << /Length 7505 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(29)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.006 Tc
+[(4)-1798(I)4(MP)13(LE)13(ME)13(N)8(T)-3(A)8(T)-3(ION)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+0.039 Tw
+[(W)7(e)-1( have consi)5(d)19(ered s)23(o)-1(ci)5(al)5( deci)5(s)3(i)5(on )20(maki)5(ng )20(and ef)21(fi)5(ci)5(ent cost )20(beari)25(ng )-20(tog)19(e)-1(ther)16(.)]TJ
+0 -1.14 TD
+0.499 Tw
+[(Impl)5(eme)19(n)-1(tati)5(on )20(i)5(s)3( )20(t)21(he thi)25(r)-4(d functi)25(on fo)19(r w)5(h)-1(i)5(c)3(h deci)5(s)3(i)5(o)19(ns abo)19(ut l)5(e)-1(vel)5( of)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(govern)20(m)-3(ent n)20(eed to )20(be m)17(ade.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.019 Tw
+[(W)7(e)-1( )20(defi)5(ne )20(i)5(m)16(pl)5(ement)21(ati)5(on )20(t)21(o)-1( be th)19(e acti)5(vi)5(ti)5(es to)19( achi)5(eve )20(non-di)5(s)23(c)3(reti)5(on)19(ary g)19(oal)5(s)]TJ
+0 -1.16 TD
+0.239 Tw
+[(set by soci)5(al)5( deci)5(s)3(i)5(o)19(n-m)16(a)-1(kers. Impl)5(e)19(m)-4(ente)19(r)-4(s )-20(may need )-20(t)21(o)-1( )-20(mak)23(e)-1( )-20(deci)5(s)3(i)5(ons)]TJ
+0 -1.14 TD
+0.08 Tw
+[(about th)18(e m)-5(o)-2(st )20(efficient a)18(ppr)-5(o)18(a)-2(ch to )20(achieve th)18(e goals )20(but th)18(ese decisions)22( )-20(will)]TJ
+0 -1.16 TD
+0.479 Tw
+[(be )20(based )40(purel)5(y )20(on obj)5(ec)23(ti)5(ve cri)5(t)1(e)19(r)-4(i)5(a)-1(, no)19(t prefe)19(r)-4(enc)23(es. If soci)25(ety has)]TJ
+T*
+0.199 Tw
+[(prefer)16(ences a)19(bout th)19(e type )20(of i)5(n)-1(str)16(u)-1(ments)23( used )-20(t)21(o)-1( )-20(achi)5(eve)19( )-20(outco)19(mes, )-20(th)19(ese)]TJ
+T*
+-0.001 Tw
+[(shoul)5(d be s)23(peci)5(f)1(i)5(ed as )20(part )20(of the )20(goal)5(s gi)5(ve)19(n to th)19(e i)5(m)-4(pl)5(e)19(m)-4(ente)19(r)-4(s.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.038 Tw
+[(In )20(comm)17(on pa)20(rl)6(ance \221)6(i)6(m)17(pl)6(emen)20(tati)6(on\222)6( us)24(ual)6(l)6(y)4( combi)26(nes obj)6(ec)24(ti)6(ve deci)6(s)4(i)6(ons )20(and)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(some subj)5(ec)23(ti)5(ve deci)5(s)3(i)5(ons,)21( but se)19(parati)25(ng the tw)25(o rol)5(e)-1(s)23( makes anal)5(ysi)5(s )-20(cl)5(ea)19(rer.)]TJ
+T*
+-0.001 Tw
+[(E)10(v)3(en i)5(f)1( central)5( )20(gover)16(nment)21( made)19( the key)23( deci)5(s)3(i)5(ons a)19(bout o)19(b)-1(j)5(e)-1(cti)5(v)3(es th)19(ere mi)5(ght)]TJ
+T*
+0.059 Tw
+[(be )20(reaso)19(n)-1(s )20(w)5(h)-1(y you)19( w)5(oul)5(d w)5(ant)21( to dev)23(ol)5(ve choi)5(ces )20(about )20(how)5( to )20(get the)19(r)-4(e. I)21(n)]TJ
+T*
+0.219 Tw
+[(thi)5(s)3( si)5(tuati)5(on tw)5(o)19( types of)21( soci)5(al)5( deci)5(s)3(i)5(o)19(ns must )20(be m)16(ade. )20(Fi)5(rst th)19(e mac)23(r)-4(o)]TJ
+0 -1.14 TD
+0.319 Tw
+[(deci)5(s)3(i)5(ons abo)19(ut envi)5(r)16(onme)19(n)-1(tal)5( outc)23(o)-1(mes, )20(and sec)23(ond th)19(e mi)5(cro)19( )-20(outco)19(mes)]TJ
+0 -1.16 TD
+0.419 Tw
+[(about r)16(egul)5(ato)19(r)-4(y i)5(n)-1(str)16(u)-1(men)19(t)1(s and l)5(o)-1(c)23(a)-1(l)5( cost sha)19(r)-4(i)5(ng. D)5(i)5(f)1(f)21(e)-1(ren)19(t)1( )-20(l)5(e)-1(vel)5(s)3( )-20(of)]TJ
+T*
+0.039 Tw
+[(govern)19(m)-4(ent )40(may )20(mak)23(e)-1( )20(these)19(.)1( )20( )20(In )20(o)19(u)-1(r )20(an)19(al)5(ysi)5(s these s)23(houl)5(d b)19(e)-1( l)5(ooked)19( at as tw)5(o)]TJ
+T*
+0.159 Tw
+[(di)5(sti)5(n)-1(ct soci)5(al)5( deci)5(s)3(i)5(ons)23( and s)23(epara)19(t)1(ed f)21(r)-4(om t)21(he actu)19(al)5( i)5(m)-4(pl)5(em)16(entati)5(o)19(n )-20(of )-20(th)19(e)]TJ
+T*
+-0.001 Tw
+[(regul)5(ato)19(r)-4(y i)5(n)-1(str)16(u)-1(ments)23( once t)21(he soci)5(al)5( d)19(e)-1(ci)5(si)5(ons a)19(r)-4(e ma)19(de.)]TJ
+0 -2.3 TD
+0.019 Tw
+[(If )20(central)5( )20(gover)16(nment)21( i)5(m)-4(pl)5(em)16(ents i)5(t)1(s ow)25(n deci)5(s)3(i)5(ons i)5(t)1( c)23(oul)5(d use)19( a seri)25(es of l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(agenci)6(e)0(s. )20( )40(For )40(exampl)6(e)20(,)2( )20(al)6(thou)20(gh )20(the)20( )20(D)6(epar)17(tment)22( of S)11(o)0(ci)6(al)6( W)8(e)0(l)6(f)2(a)20(r)-3(e has l)6(o)0(c)24(a)0(l)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(offi)5(ces, )20(they )40(are )20(co)19(ntrol)5(l)5(e)19(d )20(unde)19(r cent)21(ral)5(i)5(s)3(ed po)19(l)5(i)5(c)3(i)5(e)-1(s. In c)23(ontras)23(t, w)5(her)16(e cent)21(ral)]TJ
+T*
+0.119 Tw
+[(govern)19(m)-4(ent d)19(e)-1(ci)5(des to )20(decent)21(ral)5(i)5(s)3(e i)5(m)-4(pl)25(ement)21(ati)5(on i)5(t)1( ca)19(n )-20(w)5(r)-4(i)5(t)1(e )-20(c)23(ontrac)23(t)1(s )-20(w)5(i)5(t)1(h)]TJ
+0 -1.14 TD
+0.099 Tw
+[(l)5(o)-1(cal)5( )20(provi)5(d)-1(e)19(r)-4(s. )20(For ex)23(ampl)5(e t)21(he nati)25(onal)5( gove)19(r)-4(n)19(m)-4(ent co)19(ntracts w)5(i)5(t)21(h hospi)5(tal)5(s)]TJ
+0 -1.16 TD
+0.079 Tw
+[(to carry )20(out ce)19(rtai)5(n n)19(u)-1(mbe)19(r)-4(s of h)19(eart )20(oper)16(ati)5(ons. The )-20(h)19(o)-1(spi)5(t)1(al)5(s )-20(deci)25(de )-20(how)5( )-20(t)21(o)]TJ
+T*
+0.019 Tw
+[(do the o)19(perati)25(ons and)19( run )20(the ca)19(rdi)5(a)-1(c uni)5(t)21( but )-20(d)19(o)-1( )-20(not )-20(d)19(e)-1(ci)5(de )-20(how)25( )-20(many pati)5(ents)]TJ
+T*
+-0.001 Tw
+[(to oper)16(ate on)19( or w)5(h)-1(i)5(c)3(h )20(pati)5(ents)23( to cho)19(o)-1(se.)]TJ
+0 -2.3 TD
+0.059 Tw
+[(If )20(the )20(nati)25(onal)5( )20(gov)23(ernm)16(ent )20(i)5(ssues)23( a nati)5(o)19(nal)5( pol)5(i)5(cy st)21(ateme)19(n)-1(t, i)5(t)1( m)16(andates)23( l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.004 Tc
+0.018 Tw
+[(govern)20(m)-3(ent to)20( carry)24( out t)22(h)0(i)6(s)4( mand)20(ate. N)6(a)20(ti)6(onal)6( )-20(gov)24(ern)20(m)-3(ent )-20(set)22(s)4( )-20(the )-20(o)20(b)0(j)6(e)0(cti)6(v)4(es)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(and )20(l)5(o)-1(cal)5( )20(gov)23(ern)19(m)-4(ent )20(i)5(m)16(pl)5(eme)19(n)-1(ts the)19(m)-4(. If t)21(he l)5(o)-1(cal)5( g)19(o)-1(vern)19(ment w)5(a)19(nts to us)23(e)]TJ
+T*
+0.001 Tc
+0.021 Tw
+[(national gov)21(er)-6(n)17(m)-6(ent se)17(r)-6(v)1(ices an)17(d skills to im)-6(ple)17(m)-6(ent its)21( own policies,)19( it wr)-6(ites )-20(a)]TJ
+T*
+0.004 Tc
+0.458 Tw
+[(contract w)6(i)6(t)2(h)20( the a)20(pprop)20(ri)6(ate )20(nati)6(onal)6( )20(gover)17(nment)22( agency.)22( )-20( )-20(W)8(hen )-20(l)6(o)0(c)24(a)0(l)]TJ
+0 -1.14 TD
+0.003 Tc
+0.619 Tw
+[(govern)19(m)-4(ent )20(makes an)19(d i)5(m)-4(pl)5(e)19(m)-4(ents d)19(e)-1(ci)5(si)5(ons th)19(e tw)5(o )-20(r)16(o)-1(l)5(e)-1(s )-20(may be)]TJ
+0 -1.16 TD
+[(i)5(ndi)5(sti)5(ngui)5(shabl)5(e)19(.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.038 Tw
+[(U)6(nder )20(the)20( R)6(M)-3(A)11(,)2( l)6(o)0(cal)6( gov)24(ern)20(m)-3(ent i)6(s)4( p)20(r)-3(ovi)6(d)0(i)6(ng )20(a pr)17(ocess fo)20(r publ)6(i)6(c)4( p)20(a)0(rti)6(c)4(i)6(pati)6(o)20(n)]TJ
+0 -1.16 TD
+0.118 Tw
+[(and medi)26(ati)6(on, )20(regul)6(at)22(ory deci)6(s)4(i)6(o)20(n maki)6(n)20(g)0( \(i)6(.e.)22(:)2( pl)6(ans)24(\), and i)26(m)-3(pl)6(em)17(entati)6(o)0(n)20( of)]TJ
+0 -1.14 TD
+0.003 Tc
+0.259 Tw
+[(regul)5(ati)5(ons)23( thro)19(ugh d)19(e)-1(ci)5(si)5(ons i)5(n)-1( i)5(ndi)5(vi)5(d)19(ual)5( si)5(tuati)5(o)19(ns )-20(\(fo)19(r)-4( )-20(exa)19(m)-4(pl)5(e: resou)19(r)-4(ce)]TJ
+0 -1.16 TD
+0.079 Tw
+[(consents\). )20( Gover)16(n)-1(men)19(t)1(\222)5(s)3( othe)19(r rol)5(e)-1( i)25(n)-1( the )-20(R)25(M)-4(A)10( )-20(i)5(s)3( )-20(the )-20(col)5(l)5(e)-1(cti)5(o)19(n, )-20(anal)5(ysi)5(s and)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(provi)6(s)4(i)6(on of i)26(n)0(for)17(m)-3(ati)6(on. )20( The)20( appr)17(opri)6(a)0(t)22(e)0( )-20(l)6(e)0(vel)6( )-20(of gover)17(nmen)20(t )-20(for thi)6(s)4( )-20(functi)6(o)20(n)0( )-20(i)6(s)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(di)5(scussed i)5(n)-1( A)10(ppe)19(ndi)5(x S)10(e)-1(ven.)]TJ
+ET
+endstream endobj 197 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 198 0 obj << /Length 6995 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(30)Tj
+-34.32 58.98 TD
+0.198 Tw
+[(Local)6( gove)20(r)-3(nme)20(n)0(t may )20(regul)26(ate exte)20(rnal)6(i)6(t)2(i)6(e)0(s )20(and p)20(r)-3(ovi)6(de )-20(p)20(ubl)6(i)6(c)4( )-20(goo)20(ds )-20(mo)20(re)]TJ
+0 -1.16 TD
+0.002 Tc
+0.26 Tw
+[(effi)4(ci)4(entl)4(y)2( than)18( centr)15(a)-2(l)4( gove)18(r)-5(nme)18(n)-2(t or l)24(e)-2(ss )-20(effi)4(ci)4(entl)4(y)2(.)20( )-20( )-20(Its )-20(rel)24(a)-2(ti)4(ve )-20(effi)4(ci)4(e)18(n)-2(cy)]TJ
+T*
+0.12 Tw
+[(var)-5(i)4(es )20(by issue)18( and d)18(epends)22( on th)18(e location)18( of r)-5(e)-2(l)24(e)-2(vant inf)20(o)-2(r)-5(m)15(ation, th)18(e skills)]TJ
+T*
+0.179 Tw
+[(and reso)19(urces )20(of each )20(body, )20(and th)19(e pote)19(n)-1(ti)5(al)5( for)16( )-20(co-o)19(rdi)5(nati)5(o)19(n )-20(of )-20(l)5(o)-1(cal)5( and)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(central)5( i)5(n)-1(fo)19(rma)19(ti)5(on an)19(d deci)5(s)3(i)5(ons. )20( A)10(s)3( i)5(n)-1( )-20(the )-20(pr)16(evi)5(ous )-20(s)23(e)-1(cti)5(on, )-20(w)5(e)-1( are )-20(l)5(o)19(oki)5(ng )-20(fo)19(r)]TJ
+0 -1.16 TD
+0.04 Tw
+[(cr)-5(iter)-5(ia )20(o)18(r)-5( )20(pr)-5(inci)24(ples )20(that will h)18(e)-2(lp guid)18(e)-2( the d)18(e)-2(cision ab)18(out th)18(e m)-5(o)-2(st )20(appr)15(opr)-5(iat)20(e)]TJ
+T*
+-0.001 Tw
+[(l)5(e)-1(vel)5( of i)5(m)-4(pl)5(e)19(m)-4(entati)25(on.)]TJ
+0 -2.32 TD
+0.019 Tw
+[(Let\222)5(s)3( l)5(ook at w)5(h)19(at the)19(o)-1(ry mi)25(ght say a)19(bout w)5(h)-1(i)5(c)3(h)19( l)5(e)-1(vel)5( of govern)19(m)-4(ent )-20(i)5(s)3( the )-20(m)16(o)-1(st)]TJ
+0 -1.14 TD
+0.159 Tw
+[(effi)5(ci)5(ent i)5(m)-4(pl)5(e)19(m)-4(ente)19(r)-4(. W)7(e)-1( h)19(a)-1(ve i)5(den)19(ti)5(fi)5(ed th)19(ree c)23(r)-4(i)5(t)1(eri)5(a)-1( )20(or p)19(r)-4(i)5(n)-1(ci)5(pl)5(es )-20(to gui)5(de)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(i)5(m)-4(pl)5(ement)21(ati)5(on l)5(o)-1(ca)19(ti)5(on deci)5(s)3(i)5(o)19(ns.)]TJ
+0 -2.32 TD
+0 Tc
+0 Tw
+(1)Tj
+12 0 2.551 12 127.68 579.44 Tm
+0.001 Tc
+0.001 Tw
+[(Diseconom)-6(ies o)17(f)-1( scale: flexibility)]TJ
+12 0 0 12 127.68 565.52 Tm
+-0.001 Tc
+0.063 Tw
+[(Wh)-5(e)-5(r)-8(e)-5( lo)-5(ca)-5(l cir)-8(c)19(u)-5(m)-8(sta)15(n)-5(ce)-5(s a)-5(r)12(e)-5( d)-5(i)1(ve)-5(r)-8(s)19(e)-5(,)-3( th)-5(e)-5( b)-5(e)-5(s)-1(t )-20(im)12(p)-5(l)1(e)-5(m)-8(e)-5(n)-5(t)17(a)-5(t)-3(io)-5(n)-5( )-20(will )-20(ta)-5(ilo)15(r)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(di)5(verse sol)5(u)-1(ti)25(ons.)]TJ
+-2.36 -2.32 TD
+0 Tc
+0 Tw
+(2)Tj
+12 0 2.551 12 127.68 524 Tm
+0.002 Tc
+[(E)9(c)2(onomi)4(e)-2(s of scal)24(e)-2(: effi)4(ci)4(ency)]TJ
+12 0 0 12 127.68 510.08 Tm
+0.004 Tc
+0.078 Tw
+[(E)11(c)4(onomi)6(e)0(s can )20(ari)6(s)4(e th)20(roug)20(h provi)26(d)0(i)6(ng m)17(o)0(re o)20(f)2( a gi)6(ven)20( )-20(good or )-20(av)24(oi)6(di)6(ng)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(dupl)5(i)5(c)3(ati)5(on of)21( obj)5(ecti)5(ve )20(deci)5(s)3(i)5(ons.)]TJ
+-2.36 -2.3 TD
+0 Tc
+0 Tw
+(3)Tj
+12 0 2.551 12 127.68 468.56 Tm
+0.003 Tc
+[(Inform)16(ation)]TJ
+12 0 0 12 127.68 454.64 Tm
+0.519 Tw
+[(Impl)5(eme)19(n)-1(ters )20(need t)21(o)-1( access th)19(e rel)5(e)-1(v)23(ant i)5(n)-1(for)16(m)-4(ati)25(on ab)19(out l)5(o)-1(cal)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(condi)5(ti)5(ons an)19(d acti)5(ons )20(and t)21(e)-1(chni)5(cal)5(/)1(sci)5(enti)5(f)1(i)5(c)3( a)19(s)3(pects )20(of the i)5(ssu)19(e.)]TJ
+12 0 2.551 12 99.36 413.12 Tm
+0 Tc
+0 Tw
+(4)Tj
+0.5643 -0.02 TD
+( )Tj
+1.8157 0.02 TD
+0.003 Tc
+[(Innovati)5(o)-1(n)]TJ
+12 0 0 12 127.68 399.2 Tm
+0.34 Tw
+[(New ideas can occ)22(u)-2(r)-5( a)18(n)-2(ywher)-5(e)18(,)0( but t)20(he skills to dev)22(elop )-20(th)18(em)-5( )-20(a)18(n)-2(d)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(resourc)23(e)-1(s to di)5(ff)21(use the)19(m)-4( may)23( be m)16(o)-1(re av)23(ai)5(l)5(abl)5(e n)19(a)-1(ti)5(onal)5(l)5(y)3(.)]TJ
+-2.36 -2.32 TD
+0.159 Tw
+[(W)7(hen fl)5(exi)5(b)-1(l)5(e)-1( pol)5(i)5(c)3(i)5(e)-1(s )20(are )20(opti)5(m)-4(al)5(, )20(or i)5(f)1( g)19(ood l)5(o)-1(cal)5( i)25(n)-1(for)16(m)-4(ati)5(on )-20(i)5(s)3( essenti)5(a)-1(l)5( )-20(to)]TJ
+0 -1.14 TD
+0.26 Tw
+[(efficient )20(im)-5(ple)18(m)-5(enta)18(t)0(ion, )20(local i)24(m)-5(plem)15(entation)18( will tend to)18( be m)15(o)-2(r)-5(e)-2( e)18(fficient.)]TJ
+0 -1.16 TD
+0.08 Tw
+[(However)-5( )20(eco)18(nom)-5(ies )20(o)18(f)0( )20(scale r)15(egar)15(ding speci)24(a)-2(list skills, oper)15(ational c)22(apabilities)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(and )20(i)6(n)0(for)17(m)-3(ati)6(o)0(n)20( )20(creat)22(e )20(a case)20( for c)24(entral)6(i)6(s)4(e)20(d)0( i)6(m)-3(pl)6(e)20(m)-3(entati)26(on. W)8(ho )20(the bes)24(t)]TJ
+T*
+0.002 Tc
+0.14 Tw
+[(im)-5(plem)-5(ent)20(er)-5( )20(will )20(be )20(will )20(va)18(r)-5(y)2( )20(case by)22( case de)18(pendin)18(g)-2( on t)20(he tr)-5(a)18(de-)-5(o)18(ff am)15(ong)]TJ
+T*
+0.08 Tw
+[(these consid)18(er)-5(atio)18(ns. In so)18(m)-5(e)-2( inst)20(ances th)18(e advan)18(tages )20(of bigge)18(r)-5( size will be)]TJ
+0 -1.14 TD
+0.001 Tc
+0.121 Tw
+[(m)-6(o)-3(r)-6(e)-3( )20(c)21(r)-6(ucial. )20( )20(In)17( )20(othe)17(r)-6(s)1( )20(access t)19(o)-3( local info )20(and flexi)23(b)-3(le local soluti)23(ons will be)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(more p)20(e)0(rti)6(n)0(e)20(n)0(t.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 232.64 Tm
+0.005 Tc
+-0.023 Tw
+[(D)7(i)3(seco)16(nom)14(ies of )-20(sc)21(ale: flexi)23(bili)23(ty)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 206.48 Tm
+0.002 Tc
+0.02 Tw
+[(T)-7(he RM)-5(A)9( foc)22(u)-2(ses on )20(outcom)15(e)-2(s r)-5(a)-2(t)20(her)-5( )-20(t)20(han )-20(fixing r)-5(u)-2(les. )-20( T)-7(h)-2(is )-20(flexibility, )-20(w)24(her)-5(e a)]TJ
+T*
+0.079 Tw
+[(range o)19(f)1( beh)19(avi)5(ours )20(may al)5(l)5( achi)25(eve the)19( desi)5(r)-4(ed)19( obj)5(ecti)5(ve)19(, i)5(s)3( cruci)5(a)-1(l)5(.)1( )20( )-20(It )-20(al)5(l)5(o)-1(w)5(s)]TJ
+T*
+0.199 Tw
+[(tai)5(l)5(o)-1(r ma)19(de sol)5(u)-1(ti)5(o)19(n)-1(s to l)5(o)-1(cal)5( c)23(ondi)5(ti)5(ons.)21( Local)5( g)19(o)-1(vern)19(ment )20(may b)19(e)-1( abl)5(e )-20(t)21(o)]TJ
+T*
+0.059 Tw
+[(achi)5(eve )20(desi)25(r)-4(ed )20(ou)19(tcomes i)25(n)-1( a mo)19(re fl)5(exi)5(b)-1(l)25(e)-1( w)5(a)-1(y. If )20(there)19( are )20(di)5(secono)19(mi)5(es of)]TJ
+0 -1.14 TD
+0.159 Tw
+[(scal)5(e)-1( i)5(n)-1( the n)19(u)-1(mbe)19(r)-4( of di)5(f)21(f)1(ere)19(n)-1(t deci)5(s)3(i)5(ons)23( an au)19(thori)5(t)1(y )20(must )20(make, )-20(a )-20(s)23(m)-4(al)5(l)5(e)-1(r)]TJ
+0 -1.16 TD
+0.019 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on, w)5(h)-1(i)5(c)3(h )20(deal)5(s w)5(i)5(t)1(h f)21(e)-1(w)5(e)-1(r si)5(tu)19(ati)5(ons, ca)19(n make)19( )-20(mor)16(e)-1( )-20(di)5(vers)23(e )-20(deci)5(s)3(i)5(ons)]TJ
+T*
+0.159 Tw
+[(on )20(those )20(si)5(t)21(uati)5(ons. A)10( l)5(a)19(rger)16( autho)19(ri)5(ty m)16(a)-1(y reso)19(rt to fi)5(x)23(ed rul)25(e)-1(s that c)23(o)-1(ver a)]TJ
+T*
+0.219 Tw
+[(range o)19(f)1( si)5(tuati)5(o)19(ns. Mo)19(re di)5(ve)19(rse deci)5(s)3(i)5(o)19(ns al)5(l)5(o)-1(w)5( foc)23(u)-1(s on ac)23(hi)5(evi)5(ng gi)5(ve)19(n)]TJ
+ET
+endstream endobj 199 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 200 0 obj << /Type /Pages /Kids [ 63 0 R 71 0 R 73 0 R 205 0 R 76 0 R 210 0 R 78 0 R 82 0 R 84 0 R 87 0 R ] /Count 10 /Parent 151 0 R >> endobj 201 0 obj << /Length 8414 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(31)Tj
+-34.32 58.98 TD
+0.003 Tc
+-0.001 Tw
+[(envi)5(r)-4(onm)16(ental)5( o)19(u)-1(tcomes)23( rath)19(er th)19(an fi)5(xi)5(ng rul)5(e)-1(s )-20(fo)19(r )-20(the )-20(w)25(a)-1(y )-20(those)19( )-20(outco)19(mes )-20(ar)16(e)]TJ
+0 -1.16 TD
+[(achi)5(eved.)]TJ
+0 -2.32 TD
+0 Tc
+0.422 Tw
+[(Of co)-4(u)-4(r)-7(se)-4( t)18(h)-4(e)-4( p)16(r)-7(ice)-4( o)-4(f)-2( fle)-4(x)0(i)22(b)-4(ility ca)-4(n)-4( b)-4(e)-4( u)-4(n)-4(c)0(e)-4(r)13(ta)-4(in)-4(ty )-20(fo)16(r)-7( )-20(b)-4(u)-4(s)0(in)16(e)-4(sse)-4(s )-20(a)-4(n)-4(d)]TJ
+0 -1.14 TD
+0.002 Tc
+0.16 Tw
+[(individuals abo)18(ut how )20(r)-5(egulatio)18(ns will affect t)20(hem)-5(. )-20( T)-7(h)-2(is )-20(u)18(n)-2(cer)-5(t)0(ai)24(nty )-20(could be)]TJ
+0 -1.16 TD
+0.119 Tw
+[(deal)5(t w)5(i)5(t)1(h by w)5(o)19(rki)5(ng o)19(u)-1(t sol)5(u)-1(ti)5(ons)23( to al)5(l)5( fu)19(ture si)5(t)21(uati)5(ons i)5(n)19( advanc)23(e. T)14(h)-1(i)5(s)3( )-20(i)5(s)]TJ
+T*
+-0.001 Tw
+[(extremel)5(y c)23(o)-1(stl)5(y)3(. S)10(o)-1(l)5(u)-1(ti)5(ons )20(must b)19(e)-1( neg)19(oti)5(a)-1(ted f)21(o)-1(r si)5(tu)19(ati)5(ons )-20(th)19(at )-20(may not )-20(occ)23(u)-1(r)]TJ
+0 -1.26 TD
+0.004 Tc
+0.038 Tw
+[(for ma)20(ny years)24( i)6(f)2( at al)6(l)6(.)]TJ
+10.08 0 0 10.08 222.48 650.605 Tm
+-0.008 Tc
+(13)Tj
+12 0 0 12 233.52 647.6 Tm
+0.003 Tc
+[( A)10(l)5(ternati)5(v)3(el)5(y t)21(he j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( can s)23(e)-1(t up so)19(me g)19(eneral)]TJ
+-11.18 -1.14 TD
+0.004 Tc
+0.358 Tw
+[(gui)6(del)6(i)6(nes i)6(n)0( a)20(d)0(vance t)22(o)0( re)20(duce unc)24(ertai)6(n)20(ty but t)22(hen d)20(eal)6( )-20(w)6(i)6(t)2(h )-20(i)6(ndi)6(vi)6(du)20(al)]TJ
+0 -1.16 TD
+0.003 Tc
+0.319 Tw
+[(si)5(tuati)5(ons )20(as )20(t)21(hey ari)5(s)23(e. T)14(h)-1(i)5(s)3( saves up)19(-fro)19(nt costs b)19(u)-1(t do)19(es l)5(eave so)19(me)]TJ
+0 -1.26 TD
+-0.001 Tw
+[(uncertai)5(n)-1(ty)23( and sc)23(ope fo)19(r stra)19(tegi)5(c be)19(havi)5(our)16( to al)5(te)19(r futu)19(re d)19(e)-1(ci)5(si)5(ons.)]TJ
+10.08 0 0 10.08 469.44 607.885 Tm
+-0.008 Tc
+(14)Tj
+12 0 0 12 99.36 577.28 Tm
+0.003 Tc
+0.139 Tw
+[(D)5(i)5(s)3(economi)5(e)-1(s o)19(f)1( scal)5(e)-1( i)5(n)-1( t)21(he )-20(or)16(gani)5(sati)5(o)19(n)-1( )-20(of )-20(deci)5(s)3(i)25(on-m)16(a)-1(ki)5(ng )-20(p)19(r)-4(ocesses may)]TJ
+0 -1.16 TD
+0.179 Tw
+[(al)5(so )20(ari)5(s)3(e )20(i)5(f)1( )40(burea)19(ucraci)5(es )40(get )20(bey)23(ond )20(so)19(me cri)5(t)1(i)5(c)23(al)5( si)5(ze. S)10(m)-4(al)5(l)5( j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons)]TJ
+T*
+-0.001 Tw
+[(may be )20(more )20(fl)5(exi)5(b)-1(l)5(e)-1( an)19(d l)5(e)-1(ss bu)19(reauc)23(rati)5(c.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 521.6 Tm
+0.005 Tc
+-0.023 Tw
+[(E)12(c)1(onom)14(ies of scale)21(:)-2( )-20(ef)18(ficie)21(n)-4(cy)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 495.44 Tm
+0.003 Tc
+-0.001 Tw
+[(A)10(s)3( w)5(a)-1(s the case w)5(i)5(t)1(h c)23(o)-1(st-eff)21(ecti)5(ve deci)5(s)3(i)5(o)19(n maki)5(n)19(g)-1(, to )-20(th)19(e )-20(exten)19(t)1( )-20(that probl)5(e)19(m)-4(s)]TJ
+T*
+0.039 Tw
+[(and si)5(tuati)5(o)19(ns rep)19(eat, ce)19(ntral)5( i)5(m)16(pl)5(eme)19(n)-1(tati)5(on b)19(enefi)5(t)1(s )20(from)16( econo)19(mi)5(es of sc)23(al)5(e.)]TJ
+T*
+0.119 Tw
+[(Thi)5(s)3( i)5(s)3( par)16(ti)5(cul)5(a)-1(rl)5(y t)21(r)-4(ue w)5(h)-1(e)19(r)-4(e deci)5(s)3(i)5(o)19(ns ar)16(e heavi)5(l)5(y)3( b)19(a)-1(sed o)19(n)-1( )-20(obj)5(ecti)5(ve rath)19(er)]TJ
+0 -1.14 TD
+0.079 Tw
+[(than subj)5(ecti)5(v)23(e)-1( facto)19(r)-4(s. F)14(o)-1(r exa)19(m)-4(pl)5(e, )20(hazar)16(dous w)5(a)-1(ste)19( )-20(man)19(agem)16(ent, )-20(such)19( )-20(as)]TJ
+0 -1.16 TD
+0 Tc
+0.002 Tw
+[(th)-4(e)-4( a)-4(p)-4(p)16(r)-7(o)-4(p)-4(r)-7(ia)16(te)-4( d)-4(e)-4(s)0(ig)16(n)-4( o)-4(f)-2( la)-4(n)16(d)-4(fills, is a)-4( p)16(r)-7(o)-4(b)-4(l)2(e)-4(m)-7( i)22(n)-4( )-20(a)-4(ll )-20(ju)-4(r)-7(i)2(sd)-4(ictio)16(n)-4(s. )-20( )-20(T)11(h)-4(is )-20(is )-20(n)-4(o)-4(t)-2( a)-4(n)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(area w)5(i)5(t)1(h l)5(a)19(rge di)5(f)21(f)1(ere)19(n)-1(ces i)5(n)-1( p)19(r)-4(efer)16(ences. N)25(o)-1( )-20(one )-20(w)5(a)19(nts )-20(to )-20(b)19(e)-1( )-20(expos)23(ed )-20(to)]TJ
+T*
+0.439 Tw
+[(danger)16(ous che)19(m)-4(i)5(c)3(al)5(s w)5(hen )20(they can)19( fai)5(r)-4(l)5(y)3( ch)19(eapl)5(y avoi)5(d)19( i)5(t. )-20(D)5(e)-1(si)5(gni)5(n)19(g)]TJ
+T*
+0.3 Tw
+[(appr)-5(op)18(r)-5(i)4(ate )40(r)-5(u)-2(les )20(fo)18(r)-5( )20(landfill d)18(e)-2(sign do)18(es, howev)22(er)-5(, )20(r)-5(equir)15(e)-2( a hig)18(h)-2( level of)]TJ
+0 -1.14 TD
+0.02 Tw
+[(technical )20(info)18(r)-5(m)-5(a)-2(tio)18(n)-2( and skill. H)24(a)-2(ving on)18(e set of )20(r)-5(u)-2(les o)18(n)-2( stor)15(age of)20( haza)18(r)-5(dous)]TJ
+0 -1.16 TD
+0.3 Tw
+[(w)4(a)-2(ste )20(avoi)4(ds )20(u)18(nnecessa)18(ry )20(dupl)4(i)4(c)2(a)18(t)0(i)4(on. )20( I)20(n)-2( cases l)4(i)4(k)2(e t)20(hese, d)18(e)-2(ci)4(si)4(ons an)18(d)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(i)6(m)-3(pl)6(ement)22(ati)6(on a)20(r)-3(e bes)24(t car)17(r)-3(i)6(ed out)22( centr)17(a)0(l)6(l)6(y)4(.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.099 Tw
+[(E)10(c)3(onomi)5(e)-1(s ra)19(ther t)21(han di)5(s)23(e)-1(conomi)25(e)-1(s of scal)5(e)19( may )-20(exi)5(s)3(t)21( )-20(for )-20(p)19(r)-4(ovi)5(s)3(i)5(on of )-20(som)16(e)]TJ
+0 -1.14 TD
+0.14 Tw
+[(public goods.)20( F)-7(o)18(r)-5( exa)18(m)-5(ple, in A)9(u)-2(cklan)18(d, sewag)18(e)-2( )-20(m)-5(a)-2(n)18(agem)15(ent, )-20(lan)18(d)-2(fills, )-20(and)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(transpo)20(rtati)6(on )20(mana)20(geme)20(n)0(t, ar)17(e al)6(l)6( mo)20(re ef)22(fi)6(ci)6(entl)6(y)4( pr)17(ovi)6(ded a)20(t)2( a r)17(egi)6(onal)6( )-20(scal)26(e)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(rather)16( than v)23(e)-1(ry l)5(o)-1(cal)5(l)5(y)3(. H)25(o)-1(w)5(e)-1(ver, w)25(e)-1( can o)19(n)-1(l)5(y)3( expl)5(oi)5(t ec)23(onomi)5(e)19(s of scal)5(e)-1( i)5(f)21( )-20(the)]TJ
+T*
+0.259 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on th)19(at provi)25(des the)19( good c)23(an be )20(expand)19(ed w)5(i)5(t)1(ho)19(ut )-20(vi)5(ol)5(ati)5(ng fi)5(scal)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(equi)6(val)6(ence. )40(\(Ol)6(s)4(on, )20(1980)20(\) S)11(e)0(w)6(age t)22(r)-3(eat)22(ment i)6(n)0( )20(a spa)20(r)-3(sel)6(y)4( pop)20(ul)6(ated )20(regi)6(on)]TJ
+0 -1.14 TD
+0.001 Tc
+0.301 Tw
+[(will not necessa)17(r)-6(ily be m)14(ade m)14(o)-3(r)-6(e)-3( )-20(e)17(fficient )-20(by )-20(c)21(o)-3(m)-6(b)-3(inin)17(g )-20(that r)-6(egion )-20(wit)19(h)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(another)15(. S)9(e)-2(wage still n)18(eeds to)18( be tr)15(eated)18( close to its s)22(our)-5(ce)18(.)]TJ
+0 -2.32 TD
+0.004 Tc
+-0.002 Tw
+[(S)11(o)0(me regul)26(atory i)6(n)0(s)24(t)2(rum)17(ents m)17(a)0(y be o)20(n)0(l)6(y)4( avai)6(l)6(abl)6(e)20( to )-20(cent)22(ral)6( )-20(gov)24(ern)20(m)-3(ent. )-20( Thi)6(s)]TJ
+0 -1.16 TD
+0.003 Tc
+0.079 Tw
+[(coul)5(d be b)19(e)-1(cause o)19(f)1( l)5(i)5(n)-1(ks to o)19(t)1(her c)23(entral)5( )20(gover)16(nmen)19(t i)5(n)-1(sti)5(t)1(uti)5(ons)23(; )-20(for exampl)25(e)]TJ
+0 -2.24 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 167.36 m
+99.366 167.36 l
+S
+BT
+12 0 0 12 200.16 163.28 Tm
+( )Tj
+ET
+243.843 167.36 m
+200.163 167.36 l
+S
+BT
+10.08 0 0 10.08 99.36 151.405 Tm
+-0.008 Tc
+(13)Tj
+1.0952 -0.3095 TD
+0.111 Tw
+[( )-1333(T)-16(his)-8( is)-8( t)-16(h)0(e)24( r)-8(out)-15(e Nor)-8(t)-16(hland c)-8(hos)-8(e wit)-16(h)24( it)-16(s)-8( plan f)-16(o)0(r)15( S)-8(ignif)-16(ic)-8(ant)-16( )-24(Nat)-16(ur)-8(al )-24(A)-8(r)-8(eas)16(.)-16( )-24(S)-8(ee )-24(Cas)-8(e)]TJ
+1.7143 -1.1667 TD
+0.016 Tw
+[(S)-8(t)-16(udy)-8( I)8(I)-16(.)]TJ
+-2.8095 -2.2619 TD
+(14)Tj
+1.0952 -0.3095 TD
+[( )-1428(I)-16(n)0( t)-16(he ec)-8(onom)-8(ic)-8(s)16( lit)-16(er)-8(at)-16(ur)-8(e t)-16(his)-8( is)16( r)-8(e)0(f)-16(e)0(r)-8(r)-8(ed )24(t)-16(o)0( as)16( an inc)-8(om)-8(plet)-16(e )-24(c)-8(ont)-16(r)-8(a)0(c)-8(t)8(.)-16( )-24(O)-16(ne k)-8(e)0(y)-8( )-24(pr)-8(oblem)]TJ
+1.7143 -1.1667 TD
+0.135 Tw
+[(whic)-8(h ar)-8(is)-8(es)-8( is)-8( \223)-8(hold up\224)-8(,)-16( wher)-8(e t)-16(h)0(e)24( inv)-8(es)-8(t)-16(m)-8(ent)-16(s)16(,)-16( or)15( inf)-16(or)-8(m)-8(a)0(t)-16(ion r)-8(e)0(v)-8(elat)-16(ion of)-16( one par)15(t)-16(y)]TJ
+0 -1.1429 TD
+0.016 Tw
+[(r)-8(educ)-8(e t)-16(heir)-8( bar)-8(gaining power)-8( in f)-16(u)0(t)-16(u)0(r)-8(e)0( negot)-16(iat)-16(ions)-8(.)]TJ
+ET
+endstream endobj 202 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 203 0 obj << /Length 7602 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(32)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.119 Tw
+[(central)5( gov)23(ern)19(m)-4(ent co)19(ul)5(d )-20(i)5(m)-4(pl)5(e)19(m)-4(ent envi)5(r)-4(onm)16(ent)21(al)5( )-20(taxes )-20(th)19(roug)19(h )-20(the exi)5(s)3(ti)5(ng)]TJ
+0 -1.16 TD
+0.099 Tw
+[(tax )20(structu)19(r)-4(e. )20( A)10(r)-4(bi)5(t)21(r)-4(age)19( can l)5(i)5(m)-4(i)5(t)1( t)21(he use )20(of som)16(e)-1( i)5(n)-1(str)16(u)-1(ments )20(at a l)5(o)-1(c)23(a)-1(l)5( l)5(e)-1(vel)5(.)]TJ
+T*
+0 Tc
+0.042 Tw
+[(F)-9(o)-4(r)-7( )20(e)-4(x)20(a)-4(m)-7(p)-4(l)2(e)-4(,)-2( )40(a)-4( )20(p)-4(e)-4(t)18(r)-7(o)-4(l )20(ta)-4(x in)-4( )20(r)-7(e)-4(g)-4(i)2(o)-4(n)16( will b)-4(e)-4( in)-4(e)-4(ffe)16(ctive)-4( if p)-4(e)16(o)-4(p)-4(l)2(e)-4( a)16(r)-7(e)-4( e)-4(a)-4(s)0(ily a)16(b)-4(le)-4( to)]TJ
+T*
+0.004 Tc
+0.038 Tw
+[(dri)6(v)4(e to th)20(e nei)6(g)20(hbouri)26(ng j)6(u)0(ri)6(sdi)6(c)4(ti)26(on to )20(buy pet)22(rol)6(.)2( In)20( a )-20(di)6(ffe)20(rent exampl)6(e,)22( )-20(l)6(o)0(cal)]TJ
+0 -1.14 TD
+0.003 Tc
+0.339 Tw
+[(govern)19(m)-4(ents ca)19(nnot ef)21(fecti)5(v)3(el)5(y r)16(egul)5(ate)19( transp)19(o)-1(rta)19(t)1(i)5(on of hazar)16(dous )-20(w)5(a)-1(ste)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(because m)17(any j)6(u)0(ri)6(s)24(d)0(i)6(c)4(ti)6(ons a)20(r)-3(e affec)24(t)2(ed by )20(one )-20(l)6(o)0(a)20(d)0(. )-20( )-20(T)15(he )-20(obvi)6(o)20(us )-20(mo)20(ni)6(tori)6(ng)]TJ
+T*
+0.178 Tw
+[(poi)6(nts )20(are)20( )20(at th)20(e poi)6(nts )20(of l)6(oadi)6(n)20(g)0( and )20(unl)6(oadi)6(n)20(g)0( w)6(h)0(i)6(c)4(h coul)26(d be i)6(n)0( )20(di)6(ffere)20(nt)]TJ
+T*
+-0.001 Tc
+[(ju)-5(r)-8(i)1(sd)-5(ictio)-5(n)-5(s)-1(.)]TJ
+0 -2.3 TD
+0 Tc
+0.002 Tw
+[(T)-9(h)-4(u)-4(s)0( in)-4( so)16(m)-7(e)-4( situ)-4(a)16(t)-2(io)-4(n)-4(s)0( ce)-4(n)16(t)-2(r)-7(a)-4(l g)-4(o)-4(v)20(e)-4(r)-7(n)16(m)-7(e)-4(n)-4(t)-2( h)-4(a)16(s ca)-4(p)-4(a)16(b)-4(ilitie)-4(s th)-4(a)-4(t)-2( )20(o)-4(ffse)-4(t)-2( th)16(e)-4(i)2(r)-7( )-20(la)-4(ck)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(of flexibility and la)18(r)-5(g)-2(e)18(r)-5( bur)15(eaucr)15(a)-2(cy.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 578.96 Tm
+0.007 Tc
+[(Infor)16(m)16(a)3(ti)25(on)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 552.8 Tm
+0.003 Tc
+0.019 Tw
+[(Obj)5(e)-1(cti)5(v)3(e )20(i)5(n)-1(fo)19(rmati)5(on)19( i)5(n)-1(cl)5(udes )20(both sp)19(eci)5(a)-1(l)5(i)5(s)3(t sci)5(enti)5(f)1(i)5(c)3( a)19(nd tech)19(ni)5(cal)5( know)5(l)5(e)-1(d)19(g)-1(e)]TJ
+T*
+0.379 Tw
+[(as )20(w)5(e)-1(l)5(l)5( )20(as moni)5(t)21(o)-1(ri)5(ng i)5(n)19(for)16(m)-4(ati)5(on a)19(bout w)5(h)19(at the )20(physi)5(cal)5( eff)21(e)-1(cts of th)19(e)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(regul)6(ati)6(o)0(n)20( at i)6(ssue )20(are.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.059 Tw
+[(Local)5( )20(reg)19(u)-1(l)5(a)-1(tors )20(are l)5(i)5(k)3(el)5(y t)21(o)-1( have )20(bette)19(r access t)21(o)-1( l)5(o)-1(cal)5( i)5(n)-1(fo)19(rmati)25(on rel)25(e)-1(vant to)]TJ
+0 -1.16 TD
+0.219 Tw
+[(effi)5(ci)5(ent )20(i)5(m)-4(pl)5(e)19(m)-4(enta)19(t)1(i)5(on. )20(They ca)19(n bett)21(e)-1(r access l)25(o)-1(cal)5( obj)5(ecti)5(v)23(e)-1( i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)]TJ
+T*
+[(about physi)5(c)23(a)-1(l)5( effect. )20( Local)5( ac)23(tors may )-20(al)5(so )-20(be)19( )-20(mo)19(re )-20(l)5(i)5(k)3(el)5(y )-20(to reveal)5( thei)5(r)]TJ
+T*
+0.059 Tw
+[(i)5(n)-1(formati)25(on )20(to a)19( l)5(o)-1(cal)5( re)19(gul)5(ato)19(r)-4( w)5(hose )20(deci)5(s)3(i)5(ons th)19(ey can i)5(n)-1(fl)25(uence, )20(rathe)19(r)-4( tha)19(n)]TJ
+0 -1.14 TD
+0.019 Tw
+[(a di)5(stant ce)19(ntral)5( g)19(o)-1(vern)19(ment. )20( Local)5( d)19(e)-1(ci)5(si)5(on-m)16(a)-1(kers )20(may di)25(rectl)5(y)3( )-20(obse)19(r)-4(ve )-20(l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.004 Tc
+0.398 Tw
+[(i)6(n)0(formati)26(on )20(and)20( )20(acti)6(ons )20(a)20(nd th)20(erefo)20(r)-3(e ob)20(tai)6(n)0( m)17(oni)6(tori)6(n)20(g)0( i)6(n)0(for)17(m)-3(ati)6(o)0(n)20( mor)17(e)]TJ
+T*
+0.138 Tw
+[(effecti)6(v)4(el)6(y. )20( )40(Thei)6(r g)20(ood l)6(o)0(c)24(a)0(l)6( i)6(n)0(for)17(m)-3(ati)6(on )20(may en)20(abl)6(e l)6(o)0(cal)6( )20(deci)6(s)4(i)6(on-m)17(a)0(kers)24( to)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(tai)5(l)5(o)-1(r sol)5(u)-1(ti)5(o)19(n)-1(s to p)19(r)-4(obl)5(ems)23( effecti)5(v)3(el)5(y )20(and at)21( l)5(o)-1(w)5( cost, a)19(nd to e)19(n)-1(forc)23(e )-20(these)]TJ
+T*
+[(sol)4(u)-2(ti)4(ons.)]TJ
+0 -2.3 TD
+0.279 Tw
+[(On the ot)21(her h)19(and, ce)19(ntral)5(i)5(s)3(i)5(n)-1(g)19( contr)16(o)-1(l)5( has a)19(d)-1(vantag)19(es. C)5(ent)21(ral)5( )-20(deci)5(s)3(i)5(o)19(n-)]TJ
+0 -1.16 TD
+0.339 Tw
+[(makers )20(b)19(enefi)5(t)1( )20(f)21(r)-4(om )20(econo)19(mi)5(es of scal)25(e)-1( i)5(n)-1( i)5(n)-1(fo)19(rmati)5(o)19(n)-1(, such as)23( sci)5(enti)5(f)1(i)5(c)]TJ
+T*
+0.239 Tw
+[(know)5(l)5(edge, )20(t)21(hat )20(i)5(s)3( r)16(e)-1(l)5(e)-1(vant t)21(o)-1( a r)16(ange o)19(f)1( si)5(mi)5(l)5(a)-1(r )20(probl)5(e)19(m)-4(s. )20(They ca)19(n al)5(so)]TJ
+T*
+-0.001 Tc
+0.203 Tw
+[(e)-5(m)-8(p)-5(l)1(o)-5(y)-1( )20(p)-5(e)15(o)-5(p)-5(l)1(e)-5( )20(with)-5( )20(sp)15(e)-5(c)-1(ia)-5(lise)-5(d)-5( skills, e)-5(.)17(g)-5(.: u)-5(n)-5(d)15(e)-5(r)-8(sta)15(n)-5(d)-5(i)1(n)-5(g)-5( o)-5(f)17( RM)-8(A le)-5(g)-5(i)1(sla)-5(t)-3(io)-5(n)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(and i)5(t)1(s i)5(n)-1(ten)19(t)1(.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 275.12 Tm
+0.007 Tc
+[(I)5(nno)18(vati)25(o)-2(n)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 249.2 Tm
+0.003 Tc
+0.239 Tw
+[(Innovati)5(on i)5(s)3( )20(al)5(so i)5(m)-4(p)19(o)-1(rtan)19(t to consi)25(der w)5(h)19(en thi)5(n)-1(ki)5(n)19(g)-1( abou)19(t w)5(h)-1(i)5(c)3(h l)5(e)-1(vel)5( )20(of)]TJ
+0 -1.16 TD
+0.259 Tw
+[(gover)-4(n)19(m)-4(ent sh)19(ould im)-4(pl)25(em)-4(ent)21(. In th)19(e m)-4(e)19(dium)-4( to l)25(ong r)16(un, th)19(e ability )-20(an)19(d)]TJ
+T*
+0.079 Tw
+[(i)5(n)-1(centi)5(v)3(es of l)5(o)-1(c)23(a)-1(l)5( and ce)19(ntral)5( )20(gover)16(nments)23( to be dynami)5(c)3(al)5(l)5(y)3( effi)5(ci)5(ent may )-20(be)]TJ
+T*
+-0.001 Tw
+[(as si)5(gni)5(fi)5(cant as )20(the stati)5(c)23( di)5(ffer)16(ences.)]TJ
+0 -2.3 TD
+0.279 Tw
+[(\221)5(T)-6(echnol)5(ogy)23( chang)19(e\222)5(, or c)23(hange)19( i)5(n)-1( pol)5(i)5(c)3(i)5(e)-1(s use)19(d)-1(, consi)5(s)3(ts)23( )-20(of )-20(i)5(nnov)23(ati)5(on )-20(o)19(r)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(i)6(n)0(venti)6(on, )20(fol)6(l)6(o)0(w)26(ed by i)6(n)0(i)6(t)2(i)6(a)0(l)6( )20(adopti)6(o)20(n \(a)20(ppl)6(i)6(c)4(ati)6(on t)22(o)0( a r)17(eal)6( pro)20(b)0(l)6(e)0(m)17(\))-3( and t)22(hen)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(di)5(ffusi)5(on to si)25(mi)5(l)5(a)-1(r p)19(r)-4(obl)5(e)19(m)-4(s i)5(n)-1( di)5(ffe)19(rent )20(organi)5(s)23(a)-1(ti)5(ons. E)10(ffi)5(ci)5(ent)21( executi)5(o)19(n of)]TJ
+T*
+-0.001 Tc
+0.223 Tw
+[(e)-5(a)-5(c)-1(h)-5( )20(o)-5(f)-3( )20(th)15(e)-5(s)-1(e)-5( )20(ste)-5(p)-5(s)19( r)-8(e)-5(q)15(u)-5(ir)-8(e)-5(s)-1( a)15(p)-5(p)-5(r)-8(o)-5(p)15(r)-8(i)1(a)-5(t)-3(e)-5( skills a)15(n)-5(d)-5( a)-5(lig)-5(n)15(e)-5(d)-5( in)-5(ce)-5(n)-5(t)-3(iv)19(e)-5(s)-1(. T)10(h)-5(e)]TJ
+T*
+0.003 Tc
+0.219 Tw
+[(devel)5(opme)19(n)-1(t an)19(d di)5(ffusi)5(on)19( of new)5( )20(pol)5(i)5(cy app)19(roache)19(s suffe)19(rs fro)19(m)-4( )-20(the )-20(s)23(a)-1(me)]TJ
+0 -1.14 TD
+0.004 Tc
+0.238 Tw
+[(market f)22(a)0(i)6(l)6(u)0(res )20(as any ot)22(her f)22(o)0(rm )20(of res)24(earch a)20(nd d)20(e)0(vel)6(opm)17(ent. The )-20(n)20(e)0(w)]TJ
+0 -1.16 TD
+0.138 Tw
+[(know)6(l)6(edge i)6(s)4( a )20(publ)6(i)6(c)4( go)20(od. )20(The i)6(n)0(ve)20(ntor c)24(annot reap al)6(l)6( )-20(the )-20(b)20(enefi)6(t)2(s )-20(o)20(f)2( )-20(hi)6(s)]TJ
+ET
+endstream endobj 204 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 205 0 obj << /Type /Page /Parent 200 0 R /Resources 207 0 R /Contents 206 0 R >> endobj 206 0 obj << /Length 8357 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(33)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.219 Tw
+[(acti)5(vi)5(ty so has di)25(mi)5(ni)5(shed i)5(n)-1(c)23(enti)5(v)3(es. A)10(l)5(tho)19(ugh soci)25(ety w)5(ants t)21(o)-1( encou)19(rage)]TJ
+0 -1.16 TD
+0.039 Tw
+[(i)5(nnovati)5(on by)23( i)5(m)-4(pr)16(ovi)5(ng th)19(ese i)5(n)-1(centi)5(v)23(es, )-20(once an )-20(i)5(n)-1(n)19(o)-1(vati)5(on )-20(i)5(s)3( )-20(c)23(r)-4(eate)19(d)-1( )-20(soci)5(ety)]TJ
+T*
+-0.001 Tw
+[(w)5(ants to cha)19(r)-4(ge n)19(o)-1(thi)5(ng f)21(o)-1(r i)5(t)1(s di)5(f)21(f)1(usi)5(on.)]TJ
+0 -2.3 TD
+0.001 Tc
+0.161 Tw
+[(E)8(ffective innovatio)17(n r)-6(e)-3(q)17(u)-3(ir)-6(es hig)17(h)-3( levels of)19( capability b)17(u)-3(t m)-6(a)-3(y)21( )-20(not )-20(int)19(r)-6(insically)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(requi)5(re)19( )20(scal)5(e)-1(. )20( S)10(m)-4(al)5(l)5( u)19(n)-1(i)5(t)1(s may )20(be i)5(n)-1(n)19(o)-1(vati)5(ve an)19(d fre)19(e)-1( to ex)23(peri)5(m)16(ent w)5(i)5(t)1(h l)5(o)-1(w)]TJ
+T*
+0.359 Tw
+[(aggreg)19(ate ri)5(sk. )20( If smal)5(l)5( )20(uni)5(ts do )20(experi)25(m)-4(ent an)19(d )-20(di)5(scover)16( )-20(eff)21(e)-1(cti)5(v)3(e )-20(new)]TJ
+T*
+0.179 Tw
+[(regul)5(ato)19(r)-4(y tech)19(ni)5(ques, co)19(mmu)19(ni)5(cati)5(on b)19(e)-1(tw)5(een )20(uni)5(ts i)5(s)3( esse)19(nti)5(a)-1(l)5( for)16( )-20(effecti)5(v)3(e)]TJ
+T*
+0.004 Tc
+0.138 Tw
+[(l)6(earni)6(ng. )20(On the)20( othe)20(r han)20(d, the S)11(c)4(hu)20(mpete)20(r)-3( hyp)20(o)0(thesi)6(s)4( sug)20(gests )-20(th)20(at )-20(l)6(a)0(rg)20(e)]TJ
+0 -1.14 TD
+0.418 Tw
+[(monopol)6(i)6(e)0(s )20(\(and)20( hence l)26(a)0(rge )20(gover)17(nmen)20(tal)6( uni)6(ts\))17( )-20(are most )-20(l)6(i)6(k)4(el)6(y )-20(t)22(o)0( )-20(be)]TJ
+0 -1.16 TD
+0.002 Tc
+0.12 Tw
+[(innovative bec)22(ause of)20( their)-5( s)22(uper)15(nor)15(m)-5(a)-2(l pr)15(ofitability, an)18(d ability to)18( captu)18(r)-5(e the)]TJ
+0 -1.26 TD
+-0.001 Tw
+[(benefi)5(t)1(s i)5(n)-1(te)19(rnal)5(l)5(y)3(. E)10(m)16(pi)5(ri)5(cal)5( evi)5(d)-1(e)19(n)-1(ce on )20(thi)5(s)3( i)5(s)3( mi)5(xed)]TJ
+10.08 0 0 10.08 389.52 595.165 Tm
+-0.008 Tc
+(15)Tj
+12 0 0 12 400.56 592.16 Tm
+0 Tc
+0 Tw
+(.)Tj
+-25.1 -2.3 TD
+0.004 Tc
+0.038 Tw
+[(A)11(dopti)6(on and)20( di)6(ffusi)6(on )20(may b)20(e)0( mo)20(re effec)24(t)2(i)6(v)4(e i)6(n)0( )-20(l)6(a)0(r)17(ger govern)20(m)-3(ents.)22( )-20( )-20(E)11(m)-3(pi)6(ri)6(cal)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(evi)5(dence sug)19(gests th)19(at smal)5(l)5( co)19(mpani)25(es \(an)19(d)-1( hence)19( smal)5(l)5( )-20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons?)19(\))-4( )-20(are)]TJ
+0 -1.26 TD
+-0.001 Tw
+[(l)5(e)-1(ss l)5(i)5(k)3(el)5(y to adop)19(t new)5( tec)23(hnol)5(ogi)5(es)23(.)]TJ
+10.08 0 0 10.08 296.64 538.525 Tm
+-0.008 Tc
+(16)Tj
+12 0 0 12 307.68 535.52 Tm
+0.003 Tc
+[( Thi)5(s)3( i)5(s)3( prob)19(abl)5(y due)19( to l)5(a)-1(ck )-20(of)21( )-20(techni)5(cal)]TJ
+-17.36 -1.14 TD
+0.1 Tw
+[(capacity, high)18(er)-5( r)-5(i)4(sk )20(aver)-5(sion)18( in sm)-5(all co)18(m)-5(pani)24(es, lower)-5( )20(pr)-5(ofita)18(b)-2(ility of )-20(a given)]TJ
+0 -1.16 TD
+0.379 Tw
+[(i)5(nnovati)5(on )20(b)19(e)-1(cause )40(of smal)5(l)5(e)19(r scal)5(e)-1(, )20(and possi)25(bl)5(y l)5(a)-1(ck of acc)23(e)-1(ss to th)19(e)]TJ
+T*
+0.259 Tw
+[(necessary )20(ca)19(pi)5(tal)5(.)1( )20( )20(A)10(l)5(thou)19(gh thi)5(s)3( l)5(i)5(t)1(e)19(r)-4(atu)19(r)-4(e has )20(devel)5(op)19(ed i)5(n)-1( th)19(e context)21( of)]TJ
+T*
+-0.001 Tw
+[(pri)5(v)3(ate sect)21(or acti)5(vi)5(ti)5(es,)21( many )20(of the l)25(e)-1(ssons pr)16(obabl)5(y)23( al)5(so ap)19(pl)5(y to gov)23(ernm)16(ent.)]TJ
+0 -2.3 TD
+0.18 Tw
+[(Centr)-5(a)-2(l )20(gov)22(er)-5(n)18(m)-5(ent )20(m)15(a)-2(y )20(have)18( m)-5(o)-2(r)15(e)-2( capa)18(bility and inc)22(entive to i)24(nnovate)18( and)]TJ
+0 -1.16 TD
+0.279 Tw
+[(di)5(ffuse )20(new)5( )20(i)5(d)19(eas, )20(but)21( may n)19(o)-1(t w)5(ant t)21(o)-1( expe)19(ri)5(men)19(t)1( on a )20(nati)5(onw)5(i)5(d)19(e scal)5(e)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(because of)22( the l)6(a)20(rge ri)6(sks)24(. Mayb)20(e an appro)20(p)0(ri)6(ate)20( )-20(comp)20(romi)6(se )-20(i)6(s)4( for )-20(ce)20(ntral)]TJ
+T*
+0 Tc
+0.042 Tw
+[(g)-4(o)-4(v)0(e)-4(r)-7(n)16(m)-7(e)-4(n)-4(t)-2( to)16( fa)-4(cilita)-4(t)-2(e)-4( e)16(x)0(p)-4(e)-4(r)-7(i)22(m)-7(e)-4(n)-4(t)-2(a)-4(t)-2(io)16(n)-4( a)-4(t)-2( th)-4(e)16( lo)-4(ca)-4(l le)-4(ve)-4(l.)18( On)-4(e)-4( e)-4(x)20(a)-4(m)-7(p)-4(l)2(e)-4( )-20(w)22(h)-4(e)-4(r)-7(e)]TJ
+T*
+0.004 Tc
+0.358 Tw
+[(thi)6(s)4( )20(has )20(occu)20(rred i)6(s)4( w)6(i)6(t)22(h the )20(devel)6(op)20(ment o)20(f)2( trad)20(eabl)6(e w)6(a)20(ter )20(markets)24( i)6(n)]TJ
+0 -1.14 TD
+0.438 Tw
+[(Taran)20(a)0(ki)6( )20(w)6(her)17(e )20(a nu)20(mber)17( of cent)22(ral)6( gov)24(ern)20(m)-3(ent of)22(fi)6(ci)6(al)6(s have )20(provi)6(d)0(e)20(d)]TJ
+0 -1.16 TD
+0.003 Tc
+0.139 Tw
+[(assi)5(stance i)5(n)-1( th)19(e desi)5(g)-1(n)19( of a l)5(o)-1(c)23(a)-1(l)5(l)5(y)3( admi)5(n)-1(i)5(s)3(t)21(e)-1(red s)23(ystem w)5(h)-1(i)5(c)3(h)19( i)5(s)3( seen as )-20(a)]TJ
+0 -1.26 TD
+0.004 Tc
+0.358 Tw
+[(pi)6(l)6(o)0(t for p)20(o)0(ssi)6(bl)6(e br)17(oade)20(r i)6(m)-3(pl)6(e)20(m)-3(entati)26(on.)]TJ
+10.08 0 0 10.08 336 357.085 Tm
+-0.008 Tc
+(17)Tj
+12 0 0 12 347.04 354.08 Tm
+0.003 Tc
+0.379 Tw
+[( D)5(i)5(ffusi)5(on of n)19(e)-1(w)5( i)5(deas )20(may)]TJ
+-20.64 -1.16 TD
+-0.001 Tw
+[(si)5(mi)5(l)5(a)-1(rl)5(y need)19( to be )20(moti)5(vat)21(ed and)19( assi)5(sted f)21(r)-4(om )20(the cen)19(t)1(re.)]TJ
+0 -2.3 TD
+0.379 Tw
+[(In )20(concl)5(u)-1(si)5(on, )40(nati)5(onal)5( )40(gover)16(nmen)19(t may )20(have adv)23(antag)19(es i)5(n)-1( fun)19(d)-1(i)5(ng an)19(d)]TJ
+0 -1.16 TD
+0.14 Tw
+[(pr)-5(oviding )20(t)20(he skills for)-5( i)24(nnovatio)18(n and )20(diffusion )20(of new id)18(eas but )20(m)-5(a)-2(y wan)18(t)0( to)]TJ
+T*
+0.22 Tw
+[(facilitate expe)18(r)-5(i)4(m)-5(ent)20(ation a)18(t)0( a local lev)22(e)-2(l r)-5(a)-2(th)18(er)-5( )-20(th)18(an )-20(r)-5(i)4(sking)18( )-20(applying)18( )-20(a )-20(new)]TJ
+T*
+0.179 Tw
+[(untested i)5(d)19(ea to t)21(he w)5(hol)5(e)19( count)21(ry at o)19(n)-1(ce. W)7(h)-1(e)19(r)-4(e pol)5(i)5(c)3(i)5(e)-1(s )20(must b)19(e)-1( )-20(l)5(o)-1(cal)5(l)5(y)]TJ
+0 -1.14 TD
+0.079 Tw
+[(di)5(fferenti)5(a)19(ted, t)21(he nati)5(o)19(nal)5( gove)19(r)-4(nm)16(ent can)19(not eff)21(e)-1(cti)5(v)3(el)5(y i)5(nnov)23(ate bu)19(t may )-20(sti)5(l)5(l)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.003 Tw
+[(h)-5(a)-5(v)-1(e)-5( a)-5( r)12(o)-5(le)-5( in)-5( fa)-5(cilita)-5(t)-3(i)21(n)-5(g)-5( lo)-5(ca)-5(l in)-5(n)15(o)-5(va)-5(tio)-5(n)-5(.)]TJ
+0 -4.48 TD
+0.002 Tc
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 193.52 m
+99.366 193.52 l
+S
+BT
+12 0 0 12 200.16 189.44 Tm
+( )Tj
+ET
+243.843 193.52 m
+200.163 193.52 l
+S
+BT
+10.08 0 0 10.08 99.36 177.565 Tm
+-0.008 Tc
+(15)Tj
+1.0952 -0.3095 TD
+0.135 Tw
+[( )-1309(F)-16(o)0(r)-8( dis)-8(c)-8(u)0(s)-8(s)-8(ion and em)-8(pir)-8(ic)-8(al ev)-8(idenc)-8(e on )-24(t)-16(he )-20(S)-8(c)-8(hum)-8(pet)-16(er)-8( Hy)-8(pot)-16(hes)-8(is)-8(,)8( )-24(s)-8(ee )-24(Cohen )-24(and)]TJ
+1.7143 -1.1667 TD
+0.087 Tw
+[(Lev)-8(in,)-16( in t)-16(he Handbook)-8( of)-16( I)-16(ndus)16(t)-16(r)-8(ial O)-16(r)-8(ganis)-8(at)-16(ion \()-8(1989\))-8(.)-16( )24( )-24(F)-16(o)0(r)-8( )-24(dis)-8(c)-8(u)0(s)16(s)-8(ion )-24(on )-24(t)-16(he )-24(r)-8(elat)-16(iv)-8(e)]TJ
+0 -1.1429 TD
+0.111 Tw
+[(t)-16(i)0(m)-8(ing of)-16( innov)-8(at)-16(ion,)-16( adopt)-16(ion and dif)-16(f)-16(u)0(s)-8(ion ac)-8(r)-8(o)0(s)-8(s)16( dif)-16(f)-16(e)0(r)-8(ent)-16( f)-16(i)0(r)-8(m)-8(s)16( )-24(wit)-16(hin )-24(an )-24(indus)-8(t)-16(r)-8(y)-8( )-24(s)-8(e)0(e)]TJ
+T*
+0.016 Tw
+[(Reinganum)-8(,)-16( in t)-16(he Handbook)-8( of)-16( I)-16(ndus)-8(t)-16(r)-8(ial )24(O)-16(r)-8(ganis)-8(at)-16(ion \()-8(1989\))-8(.)]TJ
+-2.8095 -2.2619 TD
+(16)Tj
+1.0952 -0.3095 TD
+0.015 Tw
+[( )-1429(F)-16(o)0(r)-8( det)-16(ails)-8( on t)-16(h)0(e)24( em)-8(pir)-8(ic)-8(al lit)-16(er)-8(at)-16(ur)-8(e s)-8(ee K)-8(a)0(r)-8(s)-8(henas)-8( and S)16(t)-16(onem)-8(an \()-8(1995\))-8(.)]TJ
+-1.0952 -2.2857 TD
+(17)Tj
+1.0952 -0.3095 TD
+[( )-1429(P)-8(e)0(r)-8(s)-8(onal Com)-8(m)-8(unic)-8(at)-16(ion wit)-16(h Ros)-8(s)-8( P)-8(hillips)-8(on,)-16( NZ)-16( )23(T)-16(r)-8(eas)-8(ur)-8(y)-8(.)]TJ
+ET
+endstream endobj 207 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 208 0 obj << /Length 11276 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(34)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.006 Tc
+-0.004 Tw
+[(The )20(Fr)15(am)15(ewor)15(k: E)13(ffi)24(cien)17(t Im)15(plem)15(en)17(tat)19(i)4(on)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.038 Tw
+[(The ap)20(prop)20(ri)6(ate l)6(e)0(v)24(e)0(l)6( of i)6(m)-3(pl)26(ement)22(ati)6(on )-20(a)20(nd )-20(pr)17(ovi)6(s)4(i)6(on )-20(of publ)6(i)6(c)4( )-20(goo)20(ds )-20(dep)20(ends)]TJ
+0 -1.14 TD
+0.003 Tc
+0.419 Tw
+[(on )20(the )20(n)19(eed )20(fo)19(r )20(di)5(vers)23(e )20(sol)5(u)-1(ti)5(o)19(n)-1(s across)23( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(ons)23( and t)21(he exte)19(nt of)]TJ
+0 -1.16 TD
+0.079 Tw
+[(economi)5(e)-1(s )20(of scal)5(e)-1( i)5(n)-1( )20(the speci)5(f)1(i)5(c)3( )20(outpu)19(t. It al)5(so )20(depen)19(ds on t)21(he )-20(ne)19(ed )-20(for)16( )-20(and)]TJ
+T*
+0 Tc
+0.042 Tw
+[(lo)-4(ca)-4(tio)-4(n)-4( o)-4(f)-2( o)16(b)-4(je)-4(ctive)-4( in)-4(fo)16(r)-7(m)-7(a)16(tio)-4(n)-4(,)-2( skills, a)-4(n)16(d)-4( r)-7(e)-4(so)16(u)-4(r)-7(ce)-4(s, th)-4(e)-4( )-20(im)-7(p)16(o)-4(r)-7(t)-2(a)16(n)-4(ce)-4( )-20(o)-4(f)-2( )-20(lo)-4(c)20(a)-4(lly)]TJ
+T*
+0.002 Tc
+0.1 Tw
+[(obser)-5(vable)18( infor)15(m)-5(ation,)20( and t)20(he ability t)20(o)-2( access )-20(th)18(e )-20(skills )-20(and r)-5(e)-2(sou)18(r)-5(ces )-20(held)]TJ
+T*
+0 Tc
+0.002 Tw
+[(b)-4(y)0( o)-4(t)-2(h)-4(e)-4(r)-7(s.)18( T)-9(h)-4(e)16( im)-7(p)-4(o)16(r)-7(t)-2(a)-4(n)-4(c)0(e)-4( )20(o)-4(f)-2( th)-4(e)-4(s)20(e)-4( fa)-4(cto)16(r)-7(s will va)-4(r)-7(y)0( f)18(r)-7(o)-4(m)-7( issu)16(e)-4( to)-4( issu)-4(e)-4(.)]TJ
+/F3 1 Tf
+0 -2.32 TD
+0.008 Tc
+0.134 Tw
+[(Fi)6(gur)17(e 4)]TJ
+/F5 1 Tf
+4.06 0 TD
+0 Tc
+0.182 Tw
+[( illu)-4(str)-7(a)-4(t)18(e)-4(s th)-4(e)-4( i)22(m)-7(p)-4(o)-4(r)-7(t)18(a)-4(n)-4(t)-2( lin)-4(ka)-4(g)16(e)-4(s fo)-4(r)-7( e)16(fficie)-4(n)-4(t)-2( )20(p)-4(r)-7(o)-4(v)0(isio)-4(n)-4(.)18( T)-9(h)-4(is is t)18(h)-4(e)]TJ
+-4.06 -1.18 TD
+0.004 Tc
+0.078 Tw
+[(second hal)6(f )20(of the )20(devol)6(uti)6(o)20(n fra)20(m)-3(ew)6(ork)24(.)2( Th)20(e boxes )20(agai)6(n )20(repr)17(esent th)20(e fi)6(xed)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(characte)19(ri)5(sti)5(cs of an)19( i)5(ssue, w)5(h)-1(i)5(l)5(e)-1( t)21(he bu)19(bbl)5(es re)19(pres)23(ent i)5(n)-1(sti)5(t)1(uti)25(onal)5( choi)5(ces)23(.)]TJ
+/F3 1 Tf
+0 -2.82 TD
+0.005 Tc
+-0.003 Tw
+[(Figur)14(e )20(4: D)7(e)1(v)21(o)-4(lu)16(tio)16(n)-4( an)16(d E)12(ffi)23(cien)16(t P)12(r)14(ovisi)23(o)-4(n)]TJ
+ET
+0 0 0 RG
+0 J 0 j 1.92 w 10 M []0 d
+1 i
+374.88 516.32 133.92 -33.6 re
+S
+BT
+/F5 1 Tf
+11.04 0 0 11.04 400.8 504.022 Tm
+0.002 Tc
+0.003 Tw
+[(P)-5(h)-7(ys)-20(ica)-7(l)7( E)-27(ffe)-7(cts:)]TJ
+-1.4565 -1.1957 TD
+0.008 Tc
+-0.003 Tw
+[(M)-7(oni)13(tor)15(i)-9(ng Infor)15(m)-7(ati)13(o)-1(n)]TJ
+ET
+301.2 462.8 67.2 -47.04 re
+S
+BT
+11.04 0 0 11.04 311.52 450.262 Tm
+0.002 Tc
+[(Ob)-7(j)-15(e)-7(ctive)]TJ
+-0.4348 -1.1739 TD
+0.007 Tc
+[(Infor)14(m)-8(ati)12(o)-2(n)]TJ
+0.3696 -1.1739 TD
+0.008 Tc
+(and Sk)Tj
+3.1743 0 TD
+-0.005 Tc
+(ills)Tj
+-21.5438 0.0217 TD
+-0.002 Tc
+[(P)-9(o)-11(li)-19(tica)-11(l)]TJ
+0 -1.1739 TD
+[(De)-34(cisio)-12(n)]TJ
+ET
+1 J 1 j 0.72 w
+160.44 419.36 m
+160.44 419.36 l
+160.44 432.277 146.946 442.76 130.32 442.76 c
+113.694 442.76 100.2 432.277 100.2 419.36 c
+100.2 406.443 113.694 395.96 130.32 395.96 c
+146.946 395.96 160.44 406.443 160.44 419.36 c
+s
+BT
+11.04 0 0 11.04 161.52 511.702 Tm
+0.007 Tc
+[(Im)-8(pl)12(em)14(e)-24(n)-2(tati)12(on)]TJ
+ET
+240.96 516.56 m
+240.96 516.56 l
+240.96 527.622 221.499 536.6 197.52 536.6 c
+173.541 536.6 154.08 527.622 154.08 516.56 c
+154.08 505.498 173.541 496.52 197.52 496.52 c
+221.499 496.52 240.96 505.498 240.96 516.56 c
+h
+234.24 502.88 m
+307.92 462.8 l
+240.96 523.04 m
+374.88 509.6 l
+S
+BT
+9.36 0 0 9.36 288.72 479.442 Tm
+0.011 Tc
+-0.033 Tw
+[(E)11(f)33(f)7(i)28(ci)28(en)29(t)7( P)11(r)11(o)29(vi)28(si)28(on)]TJ
+ET
+207.36 496.4 m
+207.84 496.16 l
+207.12 495.44 l
+206.64 495.68 l
+207.36 496.4 l
+f*
+205.68 494.24 m
+206.16 493.76 l
+205.68 493.28 l
+205.2 493.52 l
+205.68 494.24 l
+f*
+204.24 492.08 m
+204.72 491.84 l
+204.24 490.88 l
+203.76 491.12 l
+204.24 492.08 l
+f*
+202.8 489.92 m
+203.28 489.44 l
+202.56 488.72 l
+202.08 488.96 l
+202.8 489.92 l
+f*
+201.12 487.52 m
+201.6 487.28 l
+201.12 486.56 l
+200.64 487.04 l
+201.12 487.52 l
+f*
+199.68 485.36 m
+200.16 485.12 l
+199.68 484.4 l
+199.2 484.64 l
+199.68 485.36 l
+f*
+198 483.2 m
+198.48 482.96 l
+198 482.24 l
+197.52 482.48 l
+198 483.2 l
+f*
+196.56 481.04 m
+197.04 480.8 l
+196.56 480.08 l
+196.08 480.32 l
+196.56 481.04 l
+f*
+195.12 478.88 m
+195.6 478.64 l
+194.88 477.92 l
+194.4 478.16 l
+195.12 478.88 l
+f*
+193.44 476.72 m
+193.92 476.48 l
+193.44 475.52 l
+192.96 476 l
+193.44 476.72 l
+f*
+192 474.56 m
+192.24 474.08 l
+192 473.36 l
+191.52 473.84 l
+192 474.56 l
+f*
+190.56 472.4 m
+190.8 471.92 l
+190.32 471.2 l
+189.84 471.68 l
+190.56 472.4 l
+f*
+188.88 470 m
+189.36 469.76 l
+188.88 469.04 l
+188.4 469.28 l
+188.88 470 l
+f*
+187.44 467.84 m
+187.68 467.6 l
+187.2 466.88 l
+186.72 467.12 l
+187.44 467.84 l
+f*
+185.76 465.68 m
+186.24 465.44 l
+185.76 464.72 l
+185.28 464.96 l
+185.76 465.68 l
+f*
+184.32 463.52 m
+184.56 463.28 l
+184.32 462.32 l
+183.84 462.56 l
+184.32 463.52 l
+f*
+182.88 461.36 m
+183.12 460.88 l
+182.64 460.4 l
+182.16 460.64 l
+182.88 461.36 l
+f*
+181.2 459.2 m
+181.68 458.96 l
+181.2 458 l
+180.72 458.48 l
+181.2 459.2 l
+f*
+179.52 456.8 m
+180 456.56 l
+179.52 455.84 l
+179.28 456.08 l
+179.52 456.8 l
+f*
+178.08 454.64 m
+178.56 454.4 l
+178.08 453.68 l
+177.6 454.16 l
+178.08 454.64 l
+f*
+176.64 452.48 m
+177.12 452.24 l
+176.4 451.52 l
+176.16 451.76 l
+176.64 452.48 l
+f*
+174.96 450.32 m
+175.44 450.08 l
+174.96 449.36 l
+174.48 449.6 l
+174.96 450.32 l
+f*
+173.52 448.16 m
+174 447.68 l
+173.28 447.2 l
+173.04 447.44 l
+173.52 448.16 l
+f*
+171.84 446 m
+172.32 445.76 l
+171.84 444.8 l
+171.6 445.04 l
+171.84 446 l
+f*
+170.4 443.84 m
+170.88 443.36 l
+170.4 442.64 l
+169.92 443.12 l
+170.4 443.84 l
+f*
+168.96 441.44 m
+169.44 441.2 l
+168.72 440.48 l
+168.48 440.96 l
+168.96 441.44 l
+f*
+167.28 439.52 m
+167.76 439.04 l
+167.28 438.32 l
+166.8 438.56 l
+167.28 439.52 l
+f*
+165.84 437.12 m
+166.32 436.88 l
+165.84 436.16 l
+165.36 436.4 l
+165.84 437.12 l
+f*
+164.16 434.96 m
+164.64 434.72 l
+164.16 434 l
+163.68 434.24 l
+164.16 434.96 l
+f*
+162.72 432.8 m
+163.2 432.56 l
+162.72 431.84 l
+162.24 432.08 l
+162.72 432.8 l
+f*
+161.28 430.64 m
+161.76 430.4 l
+161.04 429.44 l
+160.56 429.92 l
+161.28 430.64 l
+f*
+BT
+9.36 0 0 9.36 141.36 466.002 Tm
+-0.018 Tc
+[(S)-18(epa)-26(r)-18(a)0(b)-26(l)-1(e?)]TJ
+ET
+99.36 537.44 0.72 -0.72 re
+f*
+99.36 537.44 0.72 -0.72 re
+f*
+100.08 537.44 423.12 -0.72 re
+f*
+523.2 537.44 0.72 -0.72 re
+f*
+523.2 537.44 0.72 -0.72 re
+f*
+99.36 536.72 0.72 -141.36 re
+f*
+523.2 536.72 0.72 -141.36 re
+f*
+99.36 395.36 0.72 -0.72 re
+f*
+99.36 395.36 0.72 -0.72 re
+f*
+100.08 395.36 423.12 -0.72 re
+f*
+523.2 395.36 0.72 -0.72 re
+f*
+523.2 395.36 0.72 -0.72 re
+f*
+BT
+12 0 0 12 99.36 369.68 Tm
+0.003 Tc
+0.459 Tw
+[(Let\222)5(s)3( conti)5(n)-1(u)19(e)-1( w)5(i)5(t)1(h the s)23(ubdi)5(vi)5(si)5(on )20(exampl)5(e)19(.)1( To i)25(m)-4(pl)5(em)16(ent sub)19(d)-1(i)5(v)3(i)5(s)3(i)5(o)-1(n)]TJ
+0 -1.14 TD
+0.359 Tw
+[(deci)5(s)3(i)5(ons, )20(obj)5(ecti)5(v)23(e)-1( i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)19( i)5(s)3( i)5(m)-4(po)19(rtant f)21(o)-1(r go)19(od desi)5(g)19(n. M)16(o)-1(st l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.019 Tw
+[(govern)19(m)-4(ents )20(h)19(a)-1(ve )20(access )40(to thi)5(s)3( i)5(n)-1(f)21(o)-1(rma)19(ti)5(on bec)23(ause su)19(bdi)5(vi)5(si)5(on cont)21(rol)5( i)5(s)3( on)19(e)]TJ
+T*
+0.419 Tw
+[(of thei)5(r co)19(re fu)19(ncti)5(ons. )20(Local)5( i)5(n)-1(fo)19(rmati)25(on, such )20(as on s)23(peci)5(a)-1(l)5(i)5(s)3(ed )-20(l)5(a)-1(n)19(d)]TJ
+T*
+0.004 Tc
+0.378 Tw
+[(condi)6(ti)6(ons, )20(i)6(s)4( )20(n)20(e)0(cessary )40(for )20(a)20(ppro)20(p)0(ri)6(ate )40(desi)6(gn o)20(f)2( reg)20(u)0(l)6(a)0(ti)6(on t)22(o)0( deal)6( w)6(i)6(t)2(h)]TJ
+T*
+0.001 Tc
+0.361 Tw
+[(envir)-6(onm)14(ental ef)19(fects. L)17(o)-3(cal officials h)17(a)-3(ve )-20(r)14(e)-3(latively )-20(easy access )-20(to )-20(t)19(h)-3(is)]TJ
+0 -1.14 TD
+0.004 Tc
+0.478 Tw
+[(i)6(n)0(formati)26(on and)20( have ex)24(peri)6(e)20(nce w)6(i)6(t)2(h d)20(eal)6(i)6(ng w)6(i)6(t)2(h si)26(mi)6(l)6(a)0(r )-20(l)6(and)20( )-20(nea)20(rby.)]TJ
+0 -1.16 TD
+-0.002 Tw
+[(Moni)6(tori)6(n)20(g)0( )-20(i)6(n)0(fo)20(rmati)6(on)20(, )-20(to )-20(e)20(n)0(sure )-20(t)22(hat )-20(d)20(e)0(vel)6(ope)20(rs )-20(have fol)6(l)6(o)0(w)6(ed )-20(th)20(e )-20(re)20(gul)6(ati)6(ons,)]TJ
+T*
+0.003 Tc
+0.439 Tw
+[(i)5(s)3( essenti)5(a)-1(l)5( to g)19(ood e)19(n)-1(force)19(m)-4(ent.)21( B)10(e)-1(cause l)5(o)-1(c)23(a)-1(l)5( condi)5(ti)5(ons)23( and )-20(so)19(ci)5(al)]TJ
+T*
+0 Tc
+0.322 Tw
+[(d)-4(e)-4(c)0(isio)-4(n)-4(s)0( a)-4(r)13(e)-4( wid)-4(e)-4(l)2(y va)-4(r)-7(i)22(e)-4(d)-4(,)-2( th)-4(e)16( fle)-4(x)0(ib)-4(ility )-20(to)-4( m)-7(a)-4(tch)-4( )-20(su)16(b)-4(d)-4(i)2(visio)-4(n)-4( )-20(d)-4(e)-4(s)0(i)22(g)-4(n)-4(s)0( )-20(to)]TJ
+T*
+0.003 Tc
+0.159 Tw
+[(speci)5(f)1(i)5(c)3( )20(si)5(tuati)5(ons )40(rathe)19(r)-4( )20(tha)19(n)-1( )20(usi)5(ng )40(broa)19(d )20(rul)5(e)-1(s i)5(s)3( v)23(a)-1(l)5(uabl)5(e. )20( In thi)5(s)3( cas)23(e)-1( the)]TJ
+0 -1.14 TD
+0.359 Tw
+[(l)5(o)-1(cal)5( advanta)19(ges cl)5(ea)19(rl)5(y outw)5(e)-1(i)5(g)19(h w)5(hat n)19(a)-1(ti)5(onal)5( a)19(d)-1(vanta)19(ges )-20(may)23( )-20(exi)5(s)3(t )-20(i)5(n)]TJ
+0 -1.26 TD
+0.004 Tc
+[(i)6(m)-3(pl)6(ement)22(ati)6(on.)]TJ
+10.08 0 0 10.08 184.08 205.165 Tm
+-0.008 Tc
+(18)Tj
+12 0 0 12 99.36 174.56 Tm
+0.003 Tc
+0.159 Tw
+[(H)5(o)-1(w)5(e)-1(ver, )20(to )40(the )20(ext)21(ent )20(tha)19(t)1( expe)19(ri)5(ment)21(ati)5(on w)5(i)5(t)1(h )20(new)5( subdi)5(vi)5(si)5(o)19(n)-1( desi)5(gns,)21( or)]TJ
+0 -1.16 TD
+0 Tc
+0.022 Tw
+[(n)-4(e)-4(w)2( )20(p)-4(r)-7(o)-4(c)0(e)16(d)-4(u)-4(r)-7(e)-4(s)0( )40(fo)-4(r)-7( )20(p)16(r)-7(o)-4(c)0(e)-4(ssin)16(g)-4( a)-4(p)-4(p)-4(lica)-4(t)-2(io)16(n)-4(s)0(, fo)16(r)-7( e)-4(x)0(a)-4(m)13(p)-4(l)2(e)-4( to)-4( a)-4(llo)-4(w )20(m)-7(o)-4(r)13(e)-4( fle)-4(x)0(ib)-4(ility)]TJ
+T*
+0.002 Tc
+0.12 Tw
+[(and m)-5(o)18(r)-5(e)-2( r)-5(a)18(pid r)-5(e)-2(s)22(o)-2(lution, )20(ar)-5(e i)24(m)-5(por)-5(t)20(ant, n)18(a)-2(tional )-20(g)18(o)-2(ver)-5(n)18(m)-5(ent )-20(f)20(a)-2(cilitation )-20(m)15(a)-2(y)]TJ
+T*
+[(be )20(valuable.)20( E)9(v)2(en if a loc)22(a)-2(l gove)18(r)-5(nm)-5(e)18(n)-2(t does s)22(u)-2(ccessfully inn)18(o)-2(vate, t)20(hey will)]TJ
+0 -1.56 TD
+0 Tw
+( )Tj
+ET
+0 J
+200.166 118.16 m
+99.366 118.16 l
+S
+BT
+12 0 0 12 200.16 114.08 Tm
+( )Tj
+ET
+243.843 118.16 m
+200.163 118.16 l
+S
+BT
+10.08 0 0 10.08 99.36 102.205 Tm
+-0.008 Tc
+(18)Tj
+1.0952 -0.3095 TD
+0.016 Tw
+[( )-1428(A)-8( c)-8(ont)-16(r)-8(a)0(s)-8(t)-16(ing c)-8(a)0(s)-8(e)24( is)-8( giv)-8(en in Cas)-8(e S)16(t)-16(udy)-8( I)8(I)-16( )-24(wher)-8(e )-24(loc)-8(al )-24(gov)-8(er)-8(nm)-8(ent)-16(s)16( )-24(ar)-8(e )-24(t)-16(r)15(y)-8(ing )-24(t)-16(o)0( )-24(pr)-8(ot)-16(ec)16(t)]TJ
+1.7143 -1.1667 TD
+[(k)-8(iwi habit)-16(at)-16(.)]TJ
+ET
+endstream endobj 209 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 210 0 obj << /Type /Page /Parent 200 0 R /Resources 212 0 R /Contents 211 0 R >> endobj 211 0 obj << /Length 3451 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(35)Tj
+-34.32 58.98 TD
+0.003 Tc
+-0.001 Tw
+[(not easi)5(l)5(y)3( tr)16(ansfer)16( thei)5(r )20(experi)25(ence to )20(othe)19(r l)5(o)-1(cal)5( gov)23(ernm)16(ents. )-20( )-20(I)21(n)-1( )-20(par)16(ti)5(cul)5(a)-1(r, )-20(t)21(h)-1(e)]TJ
+0 -1.16 TD
+0.019 Tw
+[(nati)5(onal)5( )20(l)5(e)-1(vel)5( )40(gover)16(nment)21( )20(may h)19(a)-1(ve back)23(ed too )20(far o)19(u)-1(t of t)21(he i)5(m)-4(pl)5(e)19(m)-4(enta)19(t)1(i)5(on of)]TJ
+T*
+[(the new)5( m)16(andat)21(e for )20(outcom)16(e)-1(s base)19(d)-1( rat)21(her th)19(an r)16(u)-1(l)5(e)-1(s base)19(d)-1( re)19(gul)5(ati)5(on. )20( Local)]TJ
+T*
+-0.001 Tw
+[(govern)19(m)-4(ents a)19(r)-4(e havi)25(ng tr)16(oubl)5(e d)19(e)-1(vel)5(opi)5(ng )20(and a)19(dopti)5(n)-1(g)19( new)5( p)19(r)-4(acti)5(ces.)]TJ
+0 -2.3 TD
+0.004 Tc
+-0.002 Tw
+[(For m)17(any i)6(ssues,)22( both l)6(o)0(c)24(a)0(l)6( and c)24(entral)6( i)26(n)0(vol)6(v)4(eme)20(n)0(t i)6(n)0( i)6(m)17(pl)6(emen)20(tati)6(on w)6(o)20(ul)6(d )-20(be)]TJ
+0 -1.16 TD
+0.618 Tw
+[(opti)6(m)-3(al)6(. )20(Thi)6(s)4( re)20(qui)6(res )20(good c)24(o)0(-or)17(d)0(i)6(nati)6(on,)22( rega)20(rdl)6(e)0(ss )20(of w)6(her)17(e fi)6(nal)]TJ
+T*
+0.002 Tc
+0.48 Tw
+[(accountability lies. )20( T)-7(h)-2(e)18( agent)20( )-20(chosen to )-20(be ultim)-5(a)-2(tely r)-5(e)-2(spo)18(n)-2(sible )-20(fo)18(r)]TJ
+T*
+0.08 Tw
+[(im)-5(plem)-5(ent)20(ation sh)18(ould be)18( the o)18(ne with th)18(e m)-5(o)-2(st )20(advant)20(ages, a)18(nd/or)15( )-20(the )-20(a)18(b)-2(ility)]TJ
+0 -1.14 TD
+0.04 Tw
+[(to )20(contr)-5(a)-2(c)22(t)0( )20(for)-5( )40(the ot)20(her)-5(\222s skills. What)20(ever)-5( we)18( choose)18(,)0( the )20(m)-5(o)-2(st im)-5(p)18(o)-2(r)-5(t)0(a)18(n)-2(t thing)]TJ
+0 -1.16 TD
+0.079 Tw
+[(i)5(s)3( to make o)19(ne ag)19(ent ul)5(ti)25(matel)5(y)3( acco)19(untabl)5(e)19( so that)21( i)5(n)-1(centi)5(v)3(es )20(are cl)5(e)19(a)-1(r. )-20( Thi)5(s)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(avoi)6(ds the \221)6(t)2(e)20(a)0(m\222)6( p)20(r)-3(obl)6(em)17( w)6(here)20( no ag)20(ent i)6(s)4( ful)6(l)6(y)4( i)6(n)20( contr)17(o)0(l)6(,)2( )-20(and hence no )-20(age)20(nt)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(i)5(s)3( ful)5(l)5(y)3( accounta)19(b)-1(l)5(e)-1(.)]TJ
+0 -2.3 TD
+0.119 Tw
+[(U)5(n)-1(fortuna)19(tel)5(y)3(, i)5(t)1( i)5(s)3( no)19(t al)5(w)5(a)-1(ys possi)5(bl)25(e to se)19(parat)21(e the )-20(l)5(e)-1(v)23(e)-1(l)5( )-20(of )-20(p)19(r)-4(ovi)5(s)3(i)5(on )-20(f)21(r)-4(om)]TJ
+0 -1.16 TD
+0.059 Tw
+[(the l)5(e)-1(vel)5( of )20(pol)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(o)-1(n)19( maki)5(ng.)21( A)10( trad)19(e-off )-20(f)21(r)-4(equ)19(entl)5(y)3( )-20(exi)5(s)3(ts betw)5(een the)]TJ
+T*
+0.079 Tw
+[(desi)5(r)-4(e fo)19(r effi)5(ci)5(ent)21( provi)5(s)3(i)5(o)19(n and t)21(he desi)25(r)-4(e fo)19(r l)5(o)-1(cal)5( )-20(con)19(t)1(rol)5(.)1( )-20( )-20(I)21(n)-1( )-20(som)16(e)-1( )-20(cases, )-20(i)5(t)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(w)6(oul)6(d )20(seem )40(that )20(o)20(ne )20(l)6(e)0(vel)6( of)22( gove)20(r)-3(nme)20(n)0(t shoul)6(d)20( make )20(pol)6(i)6(t)2(i)6(c)4(al)6( deci)6(s)4(i)6(ons)24( and)]TJ
+T*
+0.002 Tc
+0.06 Tw
+[(another)15( )20(should i)24(m)-5(plem)15(ent the)18(m)-5(. Can)18( political acco)18(untability a)18(nd acco)18(untability)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(for effi)5(ci)5(ent)21( i)5(m)-4(pl)5(e)19(m)-4(entati)5(o)19(n be se)19(para)19(t)1(ed?)]TJ
+ET
+endstream endobj 212 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 213 0 obj << /Length 7935 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(36)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+-0.002 Tc
+0.004 Tw
+[(5)-1806(CAN WE SE)-15(PARAT)-11(E DE)6(CISION M)-9(AKING F)-11(R)0(OM)-9( IM)-9(PL)-11(EM)-9(ENT)-11(A)0(T)-11(ION)20(?)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+0.039 Tw
+[(W)7(e)-1( )20(have )20(now)5( co)19(nsi)5(der)16(ed the )20(appr)16(opri)5(a)-1(t)21(e)-1( l)5(e)-1(vel)5( of )20(gover)16(nment)21( sepa)19(ratel)5(y)3( taki)25(ng)]TJ
+0 -1.14 TD
+0.119 Tw
+[(i)5(n)-1(to account)21( the d)19(e)-1(si)5(re fo)19(r bal)5(a)19(n)-1(ced ef)21(fecti)5(v)3(e )-20(soci)5(al)5( deci)5(s)3(i)5(on )-20(m)16(a)-1(ki)5(ng, )-20(a)19(nd )-20(the)]TJ
+0 -1.16 TD
+0 Tc
+0.062 Tw
+[(d)-4(e)-4(s)0(ir)-7(e)-4( )20(fo)16(r)-7( e)-4(fficie)-4(n)-4(t)18( im)-7(p)-4(l)2(e)16(m)-7(e)-4(n)-4(t)-2(a)-4(t)-2(io)16(n)-4(.)-2( In)-4( s)20(o)-4(m)-7(e)-4( situ)16(a)-4(t)-2(io)-4(n)-4(s)0( th)16(e)-4(s)0(e)-4( two)-4( )20(o)-4(b)-4(j)2(e)-4(c)0(tive)-4(s will)]TJ
+T*
+0.003 Tc
+0.119 Tw
+[(l)5(ead )20(to )20(choi)5(c)23(e)-1(s )20(w)5(h)-1(i)5(c)3(h )20(a)19(r)-4(e )20(i)5(n)-1( ha)19(rmo)19(ny. In t)21(he case )20(of subdi)5(vi)5(si)5(o)19(n)-1(, bot)21(h soci)5(al)]TJ
+T*
+0.179 Tw
+[(deci)5(s)3(i)5(on-m)16(a)-1(ki)5(ng )20(conc)23(erns a)19(nd i)5(m)-4(pl)25(ement)21(ati)5(on su)19(ggest th)19(at l)5(o)-1(cal)5( g)19(o)-1(vern)19(ment)]TJ
+T*
+0.079 Tw
+[(shoul)5(d )20(mak)23(e)-1( )20(deci)5(s)3(i)5(ons )20(about )20(regul)25(ati)5(on. I)21(n)-1( othe)19(r cases c)23(onfl)5(i)5(c)3(ts ari)5(s)23(e and w)25(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.338 Tw
+[(w)6(oul)6(d l)6(i)6(k)4(e to hav)24(e one l)26(e)0(vel)6( of g)20(o)0(vern)20(ment )20(make d)20(e)0(ci)6(si)6(ons an)20(d anot)22(her)]TJ
+0 -1.16 TD
+0.058 Tw
+[(i)6(m)-3(pl)6(ement)22( them)17(. Fo)20(r exa)20(m)-3(pl)6(e, n)20(a)0(ti)6(onal)6( g)20(o)0(vern)20(ment )20(may w)6(ant )20(to )-20(set mi)6(ni)6(mu)20(m)]TJ
+T*
+0.003 Tc
+0.339 Tw
+[(ai)5(r qual)5(i)5(t)1(y st)21(andar)16(ds, but l)25(o)-1(cal)5( gove)19(r)-4(nm)16(ents a)19(r)-4(e abl)5(e )20(to use )20(a vari)5(ety)23( of)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(i)6(n)0(strume)20(nts to ef)22(fecti)6(v)4(el)6(y i)6(m)-3(pl)26(ement)22( them)17( w)6(here probl)26(ems )-20(a)20(r)-3(i)6(s)4(e. )-20( )-20(S)11(epa)20(rati)6(ng)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(these tw)5(o r)16(o)-1(l)5(e)-1(s re)19(qui)5(res s)23(o)-1(me f)21(o)-1(rm )20(of cont)21(ract b)19(e)-1(tw)5(een t)21(he age)19(nts.)]TJ
+0 -2.3 TD
+-0.001 Tc
+0.023 Tw
+[(A )20(co)-5(n)-5(t)-3(r)-8(a)-5(ct sp)-5(e)-5(c)-1(ifi)21(e)-5(s wh)-5(a)-5(t)-3( t)17(h)-5(e)-5( \221p)-5(r)-8(i)1(n)-5(c)-1(ip)15(a)-5(l\222 wa)-5(n)-5(t)-3(s th)15(e)-5( a)-5(g)-5(e)15(n)-5(t)-3( to)-5( d)15(o)-5(, a)-5(n)-5(d)15( h)-5(o)-5(w)1( th)-5(e)-5(y)19( will)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(be rew)6(a)20(rded a)20(nd/o)20(r)-3( puni)6(sh)20(ed i)6(n)0( r)17(e)0(l)6(a)0(ti)6(on t)22(o)0( thi)6(s)4(. )-20( )-20(I)22(n)0( )-20(the )-20(R)26(M)-3(A)11(,)2( )-20(tw)6(o )-20(scena)20(ri)6(os)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(ari)5(s)3(e, )20(the )40(pri)5(n)-1(ci)5(pal)5( )20(i)5(s)3( c)23(entr)16(a)-1(l)5( gove)19(r)-4(nme)19(n)-1(t and )20(the ag)19(ent i)5(s)3( l)5(o)-1(cal)5(,)1( )20(or vi)5(ce v)23(e)-1(rsa.)]TJ
+T*
+0.004 Tc
+0.278 Tw
+[(A)11(n)0( exampl)6(e of)22( the fi)26(rst ari)6(s)4(es)24( i)6(n)0( comp)20(ani)6(on paper)17( )-20(W)8(P)11( )-20(98/7a )-20(w)6(h)20(ere )-20(l)6(o)0(cal)]TJ
+0 -1.14 TD
+0.002 Tc
+0.04 Tw
+[(gover)-5(n)18(m)-5(ent )20(is )20(p)18(r)-5(oviding )20(kiwi )20(h)18(abitat, )40(a natio)18(nal public g)18(ood. A)9(n)-2( )20(exam)-5(ple)18( of the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.178 Tw
+[(second i)6(s)4( al)6(l)6(o)0(cati)26(on of )-20(w)6(a)20(ter ri)6(ghts )-20(th)20(roug)20(h )-20(a )-20(tr)17(adeabl)26(e )-20(w)6(a)0(ter ri)6(ghts regi)6(m)17(e)0(,)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(w)5(here )20(l)5(o)-1(cal)5( )20(govern)19(m)-4(ent )20(makes )20(deci)5(s)3(i)5(ons bu)19(t needs)23( centr)16(a)-1(l)5( assi)5(stance)19( thro)19(ugh)]TJ
+T*
+0.039 Tw
+[(changes )20(i)5(n)-1( )20(l)5(e)19(gi)5(sl)5(ati)5(on )20(a)19(nd tech)19(ni)5(cal)5( supp)19(ort. In)19( most)21( contr)16(a)-1(cts the )20(rew)5(a)-1(r)16(d)-1(s ar)16(e)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(fi)6(nanci)6(a)0(l)6(.)2( In t)22(he R)6(M)-3(A)11(,)2( m)17(o)0(st ar)17(e mo)20(re a)20(m)-3(orpho)20(us. )20(They co)20(ul)6(d )-20(be moral)6( or)]TJ
+0 -1.14 TD
+0.003 Tc
+0.079 Tw
+[(fi)5(nanci)5(a)-1(l)5( supp)19(ort fo)19(r the l)25(o)-1(cal)5( j)5(u)-1(ri)5(sdi)5(c)3(ti)25(on, )-20(bet)21(ter rel)5(a)-1(ti)5(onshi)25(ps )-20(amo)19(ng )-20(ag)19(enci)5(e)-1(s,)]TJ
+0 -1.16 TD
+0.119 Tw
+[(or )20(l)5(egal)5( )20(sa)19(ncti)5(ons )20(th)19(roug)19(h )20(the E)10(n)-1(vi)5(r)16(onme)19(n)-1(t C)5(our)16(t i)5(f)1( the c)23(ontrac)23(t)1( goal)5(s )20(are n)19(o)-1(t)]TJ
+T*
+0.004 Tc
+(met.)Tj
+0 -2.32 TD
+0.003 Tc
+0.399 Tw
+[(The r)16(u)-1(l)5(e)-1(s of g)19(ood con)19(t)1(ract )20(desi)5(gn a)19(ppl)5(y to con)19(t)1(racts)23( )-20(betw)5(e)-1(e)19(n)-1( )-20(l)5(e)-1(vel)5(s)3( )-20(of)]TJ
+0 -1.14 TD
+0.08 Tw
+[(gover)-5(n)18(m)-5(ent. Cle)18(ar)-5( obj)24(ectives and)18( lines of )20(accounta)18(b)-2(ility ar)-5(e )20(essential. )20(If they)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(are uncl)5(e)19(ar, i)5(t)1( i)5(s)3( i)25(m)-4(possi)5(bl)5(e t)21(o)-1( effecti)5(v)23(el)5(y rew)5(a)-1(r)16(d)-1( and)19( puni)5(sh.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 317.12 Tm
+0.007 Tc
+-0.005 Tw
+[(C)9(ontr)16(act)20(i)5(n)18(g pr)16(o)18(b)-2(l)5(e)3(m)16(s)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 291.2 Tm
+0.003 Tc
+-0.001 Tw
+[(Three)19( basi)5(c)3( p)19(r)-4(obl)5(ems )20(ari)5(s)3(e i)5(n)-1( c)23(ontr)16(a)-1(cts:)]TJ
+/F12 1 Tf
+0 -2.4 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.04 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(pri)6(v)4(ate i)6(n)0(fo)20(rma)20(ti)6(on ab)20(out cost )20(and qu)20(al)6(i)6(t)2(y)]TJ
+/F12 1 Tf
+-1.5 -1.22 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.04 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(pri)5(v)3(ate i)5(n)-1(fo)19(rma)19(ti)5(on ab)19(out eff)21(o)-1(rt to)19( achi)5(eve )20(goal)5(s eff)21(e)-1(cti)5(v)3(el)5(y)]TJ
+/F12 1 Tf
+-1.5 -1.24 TD
+0 Tc
+0 Tw
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.04 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(l)5(i)5(m)-4(i)5(t)1(ati)5(ons on )20(rew)5(a)-1(r)16(d)-1(s and )20(puni)5(sh)19(ments.)]TJ
+-1.5 -2.3 TD
+0.079 Tw
+[(If the ag)19(ent can )20(observ)23(e)-1( costs o)19(r)-4( qual)5(i)5(t)1(y )20(and )-20(th)19(e )-20(pri)5(n)-1(ci)25(pal)5( )-20(cann)19(ot, )-20(i)5(.)1(e. adverse)]TJ
+0 -1.16 TD
+0.179 Tw
+[(sel)5(e)-1(cti)5(on, )20(the)19( )20(pri)5(n)-1(ci)5(p)19(a)-1(l)5( )20(may )40(rew)5(a)-1(rd)19( )20(mor)16(e)-1( than)19( necessa)19(ry or)16( set pu)19(ni)5(shmen)19(t)1(s)]TJ
+T*
+0.004 Tc
+0.138 Tw
+[(i)6(napprop)20(ri)6(atel)6(y l)6(o)0(w)6( )20(and e)20(nd up w)6(i)6(t)2(h)20( an i)6(n)0(fe)20(ri)6(or )20(prod)20(uct. )-20( )-20(C)6(o)0(st may )-20(be hi)6(ghe)20(r)]TJ
+T*
+0.098 Tw
+[(and )20(per)17(form)17(ance )20(l)6(o)0(w)6(e)20(r. )20( )40(For ex)24(ampl)6(e,)22( suppose)20( cent)22(ral)6( gove)20(r)-3(nme)20(n)0(t pays l)6(o)0(c)24(a)0(l)]TJ
+T*
+0.002 Tc
+0.12 Tw
+[(gover)-5(n)18(m)-5(ent )20(to)18( )20(pr)-5(ot)20(ect )20(kiwi )20(habita)18(t. It )20(m)-5(a)-2(y not k)22(now how )20(m)-5(u)-2(ch f)20(a)-2(r)-5(m)-5(e)18(r)-5(s)2( r)-5(e)18(ally)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(need )20(to )40(be pai)6(d )20(to res)24(t)2(ri)6(ct th)20(ei)6(r l)6(and )20(use, o)20(r)-3( how)6( )20(much l)6(o)0(cal)6( )20(peopl)6(e )20(pol)6(i)6(t)2(i)6(c)4(al)6(l)6(y)]TJ
+0 -1.16 TD
+0.078 Tw
+[(oppose \()17(and t)22(heref)22(ore )20(rai)6(s)4(e th)20(e pol)6(i)6(t)2(i)6(c)4(al)6( cost )-20(o)20(f)2(\) )-20(l)6(a)20(nd )-20(use restri)6(cti)26(ons. )-20( )-20(C)6(ent)22(ral)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(govern)19(m)-4(ent )20(may not )20(be abl)5(e)19( to obs)23(erve t)21(he qual)5(i)5(t)1(y )20(of ha)19(bi)5(tat )-20(chos)23(en )-20(fo)19(r)]TJ
+ET
+endstream endobj 214 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 215 0 obj << /Length 8614 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(37)Tj
+-34.32 58.98 TD
+0.038 Tw
+[(protecti)6(on)20(. )20( )20(Thi)6(s)4( i)6(s)4( )20(a pa)20(rti)6(c)4(ul)6(arl)6(y)4( vi)6(si)6(bl)6(e )20(probl)26(em w)6(h)0(e)20(n)0( the a)20(gent i)6(s)4( p)20(a)0(i)6(d)0( to ca)20(rry)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(out the t)20(a)-2(sks.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.038 Tw
+[(If )20(the )20(ag)20(ent can )20(observ)24(e)0( the c)24(a)0(re w)6(i)6(t)2(h w)26(h)0(i)6(c)4(h deci)6(s)4(i)6(ons)24( are )20(made,)22( and t)22(he effo)20(rt)]TJ
+0 -1.14 TD
+0.003 Tc
+0.159 Tw
+[(put )20(i)5(n)-1(to )20(i)5(m)16(pl)5(emen)19(ti)5(ng )20(the)19(m)-4( w)5(h)-1(i)5(l)5(e)-1( th)19(e pri)5(n)-1(ci)25(pal)5( cann)19(ot, i)5(.)1(e. )20(moral)5( )20(hazar)16(d, i)5(t)1( i)5(s)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(di)6(ffi)6(cul)6(t)2( to pr)17(ovi)6(de a)20(pprop)20(ri)6(ate i)6(n)0(c)24(enti)6(v)4(es f)22(o)0(r eff)22(o)0(rt. )20(For )20(exampl)26(e, i)6(f)2( the c)24(entr)17(a)0(l)]TJ
+T*
+0.298 Tw
+[(govern)20(m)-3(ent set)22( ai)6(r q)20(ual)6(i)6(t)2(y stand)20(ards )20(and C)6(h)20(ri)6(stchurc)24(h)0( )-20(fai)6(l)6(s)4( )-20(to meet )-20(t)22(hose)]TJ
+T*
+0.003 Tc
+0.139 Tw
+[(standards)23( )20(i)5(n)-1( )20(a )20(p)19(a)-1(rti)5(c)3(ul)5(a)19(r)-4( )20(year)16( i)5(t)1( i)5(s)3( har)16(d to tel)5(l)5( i)5(f)1( )20(thi)5(s)3( i)5(s)3( beca)19(u)-1(se of i)5(n)-1(s)23(u)-1(ffi)5(ci)5(ent)]TJ
+T*
+0.319 Tw
+[(effort, o)19(r)-4( unc)23(ontrol)5(l)5(a)19(bl)5(e facto)19(r)-4(s such )20(as w)5(eathe)19(r, o)19(r)-4( )-20(unex)23(pected econo)19(mi)5(c)]TJ
+0 -1.14 TD
+0.004 Tc
+[(grow)6(th.)]TJ
+0 -2.32 TD
+0.378 Tw
+[(The )20(thi)26(r)-3(d )20(cont)22(racti)6(ng )40(probl)26(em )20(tha)20(t)2( )20(i)6(s)4( prev)24(al)6(ent h)20(e)0(re i)6(s)4( t)22(hat r)17(e)0(w)6(a)0(rds )20(and)]TJ
+0 -1.16 TD
+0.058 Tw
+[(puni)6(shmen)20(t)2(s )20(are)20( )20(l)6(i)6(m)-3(i)6(t)2(ed. )20( )40(In gen)20(eral)6(, t)22(he R)6(M)-3(A)11( do)20(es not )20(provi)6(de )20(centr)17(a)0(l)6( fundi)6(n)20(g)]TJ
+T*
+0.278 Tw
+[(for )20(the )40(acti)6(vi)6(ti)6(es )20(i)6(t)2( )20(re)20(qui)6(res )40(of l)6(o)0(cal)6( a)20(u)0(thori)6(t)2(i)26(e)0(s. T)15(he puni)6(s)24(h)0(ments)24( for )20(non-)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(compl)5(i)5(ance t)21(h)-1(rou)19(gh the E)10(n)-1(vi)25(ronm)16(ent C)5(o)-1(u)19(r)-4(t are)19( unce)19(r)-4(tai)5(n)-1(, sl)5(ow)5( and )-20(l)5(i)5(m)-4(i)5(t)21(ed. )-20( The)]TJ
+0 -1.16 TD
+0.319 Tw
+[(i)5(n)-1(formal)5( )40(puni)5(shm)16(ents, )20(e.)21(g.: )20(ri)5(sk )40(of l)5(o)-1(cal)5( gov)23(ern)19(m)-4(ent )20(refor)16(m)-4(, a)19(r)-4(e ext)21(r)-4(emel)5(y)]TJ
+T*
+-0.001 Tc
+0.083 Tw
+[(u)-5(n)-5(c)-1(e)-5(r)-8(ta)-5(in)-5(.)17( )20( )20(L)-5(o)-5(c)-1(a)-5(l)1( )40(g)-5(o)-5(v)-1(e)-5(r)-8(n)15(m)-8(e)-5(n)-5(t)-3( )20(is )40(e)-5(x)-1(tr)-8(e)15(m)-8(e)-5(l)1(y lim)-8(ite)-5(d)15( in)-5( its a)-5(b)-5(ility t)17(o)-5( r)-8(e)-5(wa)15(r)-8(d)-5( ce)-5(n)-5(t)17(r)-8(a)-5(l)]TJ
+T*
+0.003 Tc
+0.499 Tw
+[(govern)19(m)-4(ent a)19(genci)5(e)-1(s fo)19(r thei)25(r assi)5(stanc)23(e. )-20(T)14(hey )-20(hav)23(e )-20(l)5(i)5(m)-4(i)5(t)1(ed )-20(fi)25(nanci)5(a)-1(l)]TJ
+T*
+-0.001 Tw
+[(resourc)23(e)-1(s, and v)23(e)-1(ry l)5(i)5(ttl)5(e )20(pol)5(i)5(t)1(i)5(c)3(al)5( pow)5(e)19(r)-4(.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 468.32 Tm
+0.007 Tc
+-0.005 Tw
+[(S)14(o)-2(l)5(u)-2(ti)25(ons )20(to c)23(o)-2(n)18(t)0(r)16(acti)25(ng )20(pr)16(obl)5(em)16(s)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 442.16 Tm
+0.004 Tc
+0.018 Tw
+[(There)20( )20(are t)22(h)0(ree)20( possi)6(bl)6(e s)24(o)0(l)6(u)0(ti)6(ons to)20( the a)20(d)0(verse s)24(e)0(l)6(e)0(cti)6(on p)20(r)-3(obl)6(e)20(m)-3(. Fi)26(rst, i)6(f)2( w)6(e)]TJ
+0 -1.14 TD
+0.002 Tc
+0.04 Tw
+[(believe the c)22(apability to )20(pr)-5(od)18(uce at low)24( cost )-20(is )-20(positively r)-5(e)-2(late)18(d )-20(to )-20(th)18(e )-20(ability )-20(to)]TJ
+0 -1.16 TD
+0.079 Tw
+[(produce )20(at scal)5(e)-1(, j)25(u)-1(ri)5(sdi)5(c)3(ti)5(ons )20(may be)19( abl)5(e t)21(o)-1( be i)5(n)-1(d)19(u)-1(ced to)19( reve)19(al)5( )-20(thei)5(r )-20(c)23(o)-1(sts.)]TJ
+T*
+-0.001 Tw
+[(They coul)5(d)19( be of)21(fered)19( a choi)5(ce)19( betw)5(e)-1(e)19(n)-1( a l)5(a)-1(rg)19(e qu)19(anti)5(t)1(y )-20(of output)21( )-20(at )-20(a )-20(hi)25(gh )-20(total)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(pri)6(c)4(e and )20(a smal)6(l)6(e)20(r qua)20(nti)6(t)2(y of o)20(u)0(tput w)6(i)6(t)22(h a l)6(o)0(w)6(e)0(r)17( total)6(,)2( but )-20(hi)6(gh)20(er )-20(av)24(erage)20(,)]TJ
+T*
+0.002 Tc
+0.1 Tw
+[(pr)-5(ice. T)13(he less ef)20(ficient jur)-5(i)4(s)22(d)-2(ictions will choos)22(e the hi)24(gher)-5( )20(aver)-5(a)18(ge )-20(pr)-5(ic)22(e )-20(and)]TJ
+0 -1.14 TD
+0 Tc
+0.002 Tw
+[(lo)-4(we)-4(r)-7( o)-4(u)-4(t)-2(p)16(u)-4(t, wh)-4(ile)-4( th)16(e)-4( m)-7(o)16(r)-7(e)-4( e)-4(fficie)16(n)-4(t )-20(will )-20(fin)-4(d)-4( )-20(th)16(e)-4( )-20(la)-4(r)-7(g)16(e)-4(r)-7( )-20(co)-4(n)-4(t)18(r)-7(a)-4(ct m)-7(o)-4(r)-7(e)-4( a)-4(ttr)-7(a)-4(c)20(tive)-4(.)]TJ
+0 -1.16 TD
+0.003 Tc
+0.359 Tw
+[(Thi)5(s)3( onl)5(y w)5(o)19(rks w)5(her)16(e outp)19(u)-1(ts fro)19(m)-4( di)5(ffe)19(rent j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons )20(are su)19(bsti)5(tutes.)]TJ
+T*
+0.159 Tw
+[(S)10(e)-1(cond, w)5(e)-1( can c)23(o)-1(mpa)19(r)-4(e p)19(r)-4(oducti)5(vi)5(ty )20(and costs across )-20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons. )-20(To )-20(t)21(h)-1(e)]TJ
+T*
+0.239 Tw
+[(extent )20(tha)19(t)1( costs a)19(r)-4(e si)5(mi)5(l)5(a)19(r amo)19(ng di)5(ffe)19(rent j)25(u)-1(ri)5(sdi)5(c)3(ti)5(ons,)21( observi)25(ng rel)25(a)-1(ti)5(ve)]TJ
+T*
+0.419 Tw
+[(costs prod)19(uces i)5(n)-1(fo)19(rmati)5(o)19(n)-1( abo)19(ut each)19( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on\222)5(s )20(true c)23(o)-1(sts. T)14(h)-1(i)5(s)3( i)5(s)]TJ
+0 -1.14 TD
+0.004 Tc
+0.078 Tw
+[(parti)6(cul)6(a)0(rl)6(y )20(useful)6( fo)20(r adj)6(us)24(ti)6(ng pay)24(ments )20(over ti)26(me. )-20( Fi)6(nal)6(l)6(y)4(, )-20(w)6(h)0(e)20(r)-3(e )-20(the pri)6(v)4(ate)]TJ
+0 -1.16 TD
+0.558 Tw
+[(i)6(n)0(formati)26(on i)6(s)4( abo)20(ut qual)6(i)6(t)2(y)24(,)2( al)6(thou)20(gh )-20(qu)20(al)6(i)6(t)2(y )-20(may )-20(n)20(o)0(t )-20(be )-20(i)26(mmedi)26(atel)6(y)]TJ
+T*
+0.078 Tw
+[(observabl)6(e)20( or )20(rew)6(a)0(rd)20(abl)6(e, i)6(t)2( )20(may bec)24(ome o)20(b)0(vi)6(ous ov)24(er ti)6(m)17(e)0(. )-20(Fu)20(ture )-20(c)24(ontr)17(a)0(cts)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(may depe)19(nd on)19( the g)19(ood r)16(eputati)25(on hi)5(gh )20(qual)5(i)5(t)1(y )-20(ou)19(tputs )-20(g)19(ener)16(ate. )-20( )-20(If)21( )-20(creati)5(n)19(g)]TJ
+T*
+0.004 Tc
+0.398 Tw
+[(reputati)6(o)20(ns )20(i)6(s)4( i)6(m)-3(po)20(rtant)22( i)6(t)2( i)6(s)4( cri)6(t)2(i)6(c)4(al)6( to)20( mai)6(n)0(t)22(a)0(i)6(n)0( and )20(devel)6(op i)26(n)0(sti)6(t)2(uti)6(o)0(n)20(a)0(l)]TJ
+0 -1.14 TD
+0.006 Tc
+[(memory)26(.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.119 Tw
+[(W)7(hen i)5(t)1( i)5(s)3( di)5(ffi)5(cul)5(t)1( to)19( obse)19(r)-4(ve effo)19(rt, ef)21(fort i)5(s)3( )20(often )20(rew)5(a)-1(rd)19(ed i)5(ndi)25(rectl)5(y)3( )-20(th)19(rough)]TJ
+0 -1.26 TD
+0.005 Tc
+0.377 Tw
+[(rew)7(a)1(rds)5( f)23(o)1(r o)21(b)1(s)5(e)1(rv)5(abl)27(e outp)21(u)1(ts)5(.)]TJ
+10.08 0 0 10.08 281.04 180.445 Tm
+-0.008 Tc
+(19)Tj
+12 0 0 12 292.08 177.44 Tm
+-0.002 Tc
+0.384 Tw
+[( Po)-6(litica)-6(lly d)-6(e)-6(s)-2(ir)-9(e)-6(d)-6( o)-6(u)-6(t)-4(c)18(o)-6(m)-9(e)-6(s a)14(r)-9(e)-6( )-20(id)-6(e)14(a)-6(lly)]TJ
+-16.06 -1.14 TD
+0.003 Tc
+0.199 Tw
+[(achi)5(eved )20(by c)23(ontrac)23(t)1(i)5(ng fo)19(r speci)5(f)1(i)5(c)3( n)19(on-di)5(sc)23(reti)5(ona)19(ry out)21(puts. U)5(n)-1(f)21(o)-1(rtun)19(atel)5(y)]TJ
+0 -1.16 TD
+0.479 Tw
+[(measur)16(abl)5(e out)21(puts, th)19(at rel)25(a)-1(te cl)5(ea)19(rl)5(y )-20(to )-20(ou)19(tcomes,)21( )-20(are frequ)19(entl)5(y)3( )-20(no)19(t)]TJ
+T*
+0.039 Tw
+[(avai)5(l)5(abl)5(e. D)5(e)-1(fi)5(ni)5(ti)5(o)19(n)-1( of so)19(me ou)19(tputs, t)21(hat a)19(r)-4(e pa)19(rt of t)21(he )-20(effi)5(ci)5(e)19(n)-1(t )-20(pro)19(ducti)5(on of)]TJ
+T*
+0.004 Tc
+0.218 Tw
+[(outcomes, w)6(i)6(t)22(hout i)6(n)0(c)24(enti)6(v)4(es fo)20(r the othe)20(r )-20(non-m)17(eas)24(urabl)6(e)20( )-20(outpu)20(ts )-20(tends to)]TJ
+0 -1.62 TD
+0.002 Tc
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(19)Tj
+1.0952 -0.3095 TD
+0.016 Tw
+[( )-1428(T)-16(his)-8( is)-8( t)-16(h)0(e)24( s)-8(t)-16(andar)-8(d pr)-8(oblem)-8( of)8( m)-8(o)0(r)-8(al haz)-8(ar)-8(d.)]TJ
+ET
+endstream endobj 216 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 217 0 obj << /Length 8124 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(38)Tj
+-34.32 58.98 TD
+0.058 Tw
+[(l)6(ead to se)20(ri)6(ous mi)6(sal)6(l)6(o)0(c)24(a)0(ti)6(on o)20(f)2( effo)20(rt tow)6(a)20(rd me)20(asura)20(b)0(l)6(e)0(, )-20(rew)26(a)0(rde)20(d)0( )-20(outp)20(u)0(ts. )-20( )-20(It)]TJ
+0 -1.16 TD
+0.003 Tc
+0.219 Tw
+[(may be p)19(r)-4(efe)19(r)-4(abl)5(e t)21(o)-1( rew)5(a)19(rd on )20(the ba)19(si)5(s of a m)16(easu)19(r)-4(e of )-20(t)21(he )-20(outc)23(o)-1(me )-20(o)19(f)]TJ
+T*
+0.239 Tw
+[(i)5(n)-1(terest. )20( )20(H)5(e)19(re a )20(trad)19(eoff a)19(r)-4(i)5(s)3(es betw)5(e)19(en gi)5(vi)5(ng )20(unbal)5(a)19(n)-1(ced i)5(n)-1(ce)19(nti)5(v)3(es, an)19(d)]TJ
+T*
+0.059 Tw
+[(gi)5(vi)5(ng w)5(eak i)5(n)-1(cen)19(t)1(i)5(v)3(es and)19( forci)5(n)-1(g)19( agen)19(ts to be)19(ar ri)5(sk w)25(hen th)19(ey are)19( )-20(rew)5(a)19(rded)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(on the b)19(a)-1(si)5(s of outc)23(o)-1(mes t)21(hey onl)5(y )20(parti)5(al)5(l)5(y)3( con)19(t)1(rol)5(.)]TJ
+0 -2.32 TD
+0.14 Tw
+[(T)-7(he inability )20(to r)-5(e)-2(wa)18(r)-5(d)-2( o)18(r)-5( punis)22(h)-2( sufficiently has )-20(no dir)-5(e)-2(ct )-20(sol)24(u)-2(tion )-20(ot)20(her)-5( )-20(t)20(han)]TJ
+0 -1.16 TD
+0.099 Tw
+[(fi)5(ndi)5(ng )20(addi)5(ti)25(onal)5( )20(r)16(e)-1(sourc)23(e)-1(s to i)5(n)-1(cr)16(ease i)5(n)-1(c)23(enti)5(v)3(es. N)5(o)19(n-fi)5(na)19(nci)5(a)-1(l)5( i)5(n)-1(centi)5(v)3(es )20(to)]TJ
+T*
+0.159 Tw
+[(encoura)19(ge )20(vol)5(u)-1(n)19(t)1(ary co)19(mpl)5(i)5(ance )20(may b)19(e)-1( w)5(o)-1(rth)19( expl)5(ori)25(ng. Oth)19(erw)5(i)5(s)3(e r)16(eal)5(i)5(s)3(ti)5(c)]TJ
+0 -1.14 TD
+0.239 Tw
+[(l)5(i)5(m)-4(i)5(t)1(s shoul)5(d b)19(e)-1( put o)19(n)-1( expect)21(a)-1(ti)5(ons so)19( that l)5(i)5(m)-4(i)5(t)21(ed )-20(res)23(ources)23( )-20(are used )-20(as)]TJ
+0 -1.16 TD
+0.079 Tw
+[(effecti)5(v)3(el)5(y as p)19(o)-1(ssi)5(bl)5(e. U)5(n)19(real)5(i)5(s)3(ti)5(c, un)19(enforc)23(eabl)5(e )20(manda)19(tes may)23( backfi)5(r)16(e )-20(and)]TJ
+T*
+-0.001 Tw
+[(make futu)19(re acti)25(on even)19( mo)19(re difficult.)]TJ
+12 0 2.551 12 99.36 565.52 Tm
+[(Inform)16(al)5( / N)5(on-)16(fi)5(nanci)5(a)-1(l)5( co)19(ntracts)]TJ
+12 0 0 12 99.36 539.84 Tm
+0.179 Tw
+[( )180(A)10( contract d)19(oes not )20(need )20(to be )20(a w)5(r)-4(i)5(tten)19(,)1( stri)5(ctl)5(y)3( )-20(en)19(force)19(abl)5(e )-20(doc)23(ument)21(. )-20( )-20(A)]TJ
+T*
+0.339 Tw
+[(contract )20(i)5(n)-1( )40(many )20(c)23(a)-1(ses i)5(s)3( mo)19(re of)21( a rel)25(a)-1(ti)5(onshi)5(p. )20( W)7(hen th)19(e cont)21(racti)5(n)-1(g)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(probl)6(ems)24( )20(above )20(c)24(annot )40(be cl)6(ea)20(rl)6(y sol)6(v)4(ed t)22(he i)6(n)0(fo)20(rmal)6( el)26(ements)24( of a co)20(ntract)]TJ
+T*
+0.018 Tw
+[(become )20(more)20( i)6(m)-3(po)20(rtant. P)11(e)20(rsonal)6( )20(rel)6(a)0(ti)6(ons)24(hi)6(ps betw)6(e)20(en offi)6(ci)6(al)6(s )20(at cent)22(ral)6( and)]TJ
+T*
+0.578 Tw
+[(l)6(o)0(cal)6( )20(govern)20(m)-3(ent )20(l)26(e)0(vel)6(s)4(, )20(conc)24(ern by i)26(m)-3(pl)6(em)17(enters)24( for t)22(hei)6(r )20(reput)22(ati)6(on,)]TJ
+0 -1.14 TD
+0.003 Tc
+0.079 Tw
+[(promoti)25(on i)5(n)-1(centi)5(v)23(es, and)19( publ)5(i)5(c)3(i)5(t)1(y fo)19(r )-20(successes)23( )-20(and )-20(f)21(a)-1(i)5(l)5(u)-1(res )-20(al)5(l)5( provi)5(d)-1(e)19( )-20(mor)16(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.178 Tw
+[(di)6(ffuse )20(i)6(n)0(centi)6(v)24(es )20(for )40(good )20(perfo)20(rma)20(nce. B)11(u)0(i)6(l)6(d)0(i)6(ng )20(a good)20( \223cor)17(pora)20(t)2(e cul)6(t)2(u)20(r)-3(e\224)]TJ
+T*
+0.338 Tw
+[(may )20(be )20(as )20(i)26(m)-3(po)20(rtant as)24( the fo)20(rmal)6( )20(rul)6(e)0(s fo)20(r enc)24(oura)20(g)0(i)6(ng pri)26(de an)20(d hi)6(gh)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(producti)5(vi)5(ty. )20( Thes)23(e aspects)23( cannot)21( be cr)16(eated )20(overni)25(ght but)21( can be)19( )-20(destr)16(oyed.)]TJ
+T*
+0.319 Tw
+[(A)10(n)-1(y refor)16(m)-4( shoul)5(d )20(pay att)21(enti)5(on t)21(o)-1( pre)19(s)3(ervi)5(ng b)19(enefi)5(c)3(i)5(a)-1(l)5( rel)5(a)-1(ti)5(on)19(shi)5(p)-1(s )-20(an)19(d)]TJ
+0 -1.14 TD
+0.159 Tw
+[(practi)5(ces an)19(d mai)5(n)19(tai)5(n)-1(i)5(ng )20(good as)23(pects of c)23(o)-1(rpo)19(r)-4(ate c)23(u)-1(l)5(t)1(ure,)21( such )-20(as mor)16(a)-1(l)5(e)]TJ
+0 -1.16 TD
+0.019 Tw
+[(and tea)19(m)-4( spi)5(r)-4(i)5(t. )20(Thes)23(e aspects )20(are l)5(e)-1(ss)23( ame)19(nabl)5(e to)19( har)16(d anal)5(ysi)5(s )-20(b)19(u)-1(t )-20(beco)19(m)-4(e)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(cri)6(t)2(i)6(c)4(al)6( w)6(hen ot)22(her f)22(o)0(rms )20(of cont)22(ract a)20(r)-3(e w)6(eak. )20( N)6(on )-20(fi)6(na)20(nci)6(a)0(l)6( )-20(i)6(n)0(centi)6(v)4(es)24( )-20(are an)]TJ
+T*
+0.178 Tw
+[(area th)20(at, i)6(n)0( th)20(e N)6(e)0(w)6( Ze)20(al)6(and )20(publ)6(i)6(c)4( secto)20(r)-3( refo)20(rms)24(, may h)20(a)0(ve )-20(be)20(en )-20(un)20(der-)]TJ
+T*
+0.003 Tc
+[(expl)5(oi)5(ted.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 317.6 Tm
+0.005 Tc
+-0.003 Tw
+[(A)7(d)-4(van)16(tage)21(s o)16(f)-2( se)21(par)14(a)1(tin)16(g)-4( p)16(o)-4(lit)18(ical a)21(nd im)14(pl)23(em)14(ent)18(a)1(tio)16(n)-4( r)14(o)-4(le)21(s: )-20(t)18(h)-4(e )-20(r)14(e)1(g)16(u)-4(lat)18(o)-4(r)]TJ
+0.2508 -1.18 TD
+0.003 Tc
+-0.001 Tw
+[(/ p)-6(r)12(o)-6(v)-1(id)14(er)12( sp)-6(li)21(t)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 277.28 Tm
+0.004 Tc
+0.018 Tw
+[(C)6(o)0(mbi)6(n)0(i)6(ng )20(t)22(he )20(pol)6(i)6(t)2(i)6(c)4(al)6( )20(a)20(nd )20(i)6(m)-3(pl)26(ement)22(ati)6(on r)17(o)0(l)6(e)0(s can )20(al)6(so cre)20(a)0(te p)20(r)-3(obl)6(ems)24(.)2( Fo)20(r)]TJ
+0 -1.16 TD
+0.003 Tc
+0.079 Tw
+[(exampl)5(e, l)5(o)-1(c)23(a)-1(l)5( gove)19(r)-4(nme)19(n)-1(ts may )20(face a c)23(onfl)5(i)5(c)3(t betw)25(een )-20(th)19(ei)5(r )-20(deci)5(s)3(i)5(o)19(ns )-20(unde)19(r)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(the R)6(M)-3(A)11( and t)22(hei)6(r p)20(r)-3(ovi)6(s)4(i)6(on )20(of i)6(n)0(fras)24(tructu)20(re. L)20(o)0(cal)6( gov)24(ernm)17(ent )-20(p)20(r)-3(ovi)6(des )-20(l)6(o)0(c)24(a)0(l)]TJ
+T*
+0.078 Tw
+[(i)6(n)0(frastruc)24(ture )20(s)24(e)0(rvi)6(c)4(es. I)22(t)2( i)6(s)4( di)6(ffi)6(cul)6(t)2( f)22(o)0(r th)20(em to )20(pl)6(an th)20(e man)20(ageme)20(n)0(t of t)22(hese)]TJ
+0 -1.14 TD
+0.038 Tw
+[(assets \(as )20(requi)26(red un)20(der t)22(he Loc)24(al)6( Gover)17(n)0(ment)22( A)11(c)4(t\) )-20(w)6(hen they )-20(can)20(not )-20(con)20(t)2(rol)]TJ
+0 -1.16 TD
+0.003 Tc
+0.079 Tw
+[(w)5(here new)5( )20(devel)5(op)19(ment t)21(a)-1(kes pl)5(ace)19(.)1( Th)19(ey ther)16(efor)16(e have )20(a tend)19(ency )-20(to over-)]TJ
+T*
+0.24 Tw
+[(contr)-5(o)-2(l co)18(m)-5(m)-5(e)18(r)-5(c)2(ial activity. )20(T)-7(h)-2(is illustr)-5(a)18(tes the )20(advant)20(ages of)20( a r)-5(e)18(gulato)18(r)-5( /)]TJ
+T*
+0.039 Tw
+[(provi)5(der)16( spl)5(i)5(t. In s)23(o)-1(me )-20(si)5(t)21(uati)5(ons, )-20(i)5(f)1( deci)5(s)3(i)5(ons )-20(a)19(r)-4(e )-20(m)16(ade )-20(by those deal)5(i)5(ng )-20(o)19(n)-1( )-20(a)]TJ
+T*
+[(day )20(to )20(day )40(basi)5(s)3( )20(w)5(i)5(t)1(h )20(th)19(e )20(l)5(andow)25(ners a)19(nd i)5(ndus)23(tri)5(e)-1(s th)19(ey reg)19(u)-1(l)5(a)-1(te, t)21(he re)19(gul)5(ato)19(r)]TJ
+0 -1.14 TD
+0.004 Tc
+0.178 Tw
+[(mi)6(ght be \221)6(c)4(a)20(p)0(tur)17(ed\222)6( and )20(fai)6(l)6( to r)17(epres)24(ent th)20(e w)6(i)6(der i)6(n)20(terests)24( )-20(of )-20(soci)6(ety.)22( )-20( )-20(Th)20(e)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(probl)5(em)16( )20(of )20(\221)5(c)3(apt)21(ure\222)5( )20(m)16(a)-1(y )20(be l)5(e)-1(ss)23( acute i)5(n)19( the R)5(M)-4(A)10( b)19(e)-1(cause w)5(e)19( are )20(deal)5(i)5(ng w)5(i)5(t)1(h)]TJ
+T*
+0.439 Tw
+[(di)5(rectl)5(y)3( pol)5(i)5(t)1(i)5(c)3(al)5(l)5(y)3( acc)23(ountabl)25(e bodi)5(es )20(al)5(thou)19(gh, gi)5(ven)19( the )-20(fai)5(l)5(u)19(res )-20(of)21( )-20(the)]TJ
+T*
+0.119 Tw
+[(democr)16(a)-1(ti)5(c proc)23(ess, si)5(mi)5(l)5(a)-1(r)16( pro)19(b)-1(l)5(e)-1(ms m)16(a)-1(y ari)5(s)3(e)19(.)1( )-20(In )-20(a)19(ddi)5(ti)5(on, )-20(t)21(he )-20(pr)16(obl)5(ems of)]TJ
+T*
+0.259 Tw
+[(regul)5(ato)19(r)-4(y )20(capt)21(ure )40(may )20(som)16(e)-1(ti)5(me )40(be )20(ove)19(r)-4(stated)19( rel)5(a)-1(ti)5(ve)19( to the)19( advant)21(ages,)]TJ
+ET
+endstream endobj 218 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 219 0 obj << /Length 11114 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(39)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.319 Tw
+[(trust, )20(coo)19(perati)25(on and)19( good)19( i)5(n)-1(for)16(m)-4(ati)5(on fl)25(ow)5(s, that cl)25(ose rel)5(a)19(ti)5(onshi)5(ps c)23(a)-1(n)]TJ
+0 -1.16 TD
+0.004 Tc
+[(generat)22(e.)]TJ
+/F3 1 Tf
+0 -2.6 TD
+0.007 Tc
+-0.005 Tw
+[(The )20(Fr)16(am)16(ew)5(or)16(k: T)18(h)-2(e W)11(h)18(ol)5(e P)14(i)5(c)23(t)0(ur)16(e)]TJ
+0 -2.16 TD
+0.008 Tc
+-0.026 Tw
+[(Fi)6(gur)17(e 5)]TJ
+/F5 1 Tf
+3.9 0 TD
+0.003 Tc
+-0.001 Tw
+[( combi)25(nes )]TJ
+/F3 1 Tf
+4.84 0 TD
+0.008 Tc
+-0.006 Tw
+[(Fi)26(gur)17(e 3)]TJ
+/F5 1 Tf
+3.9 0 TD
+0.004 Tc
+-0.022 Tw
+[( and )]TJ
+/F3 1 Tf
+2.2 0 TD
+0.009 Tc
+-0.007 Tw
+[(Fi)7(g)20(u)0(r)18(e)5( 4)]TJ
+/F5 1 Tf
+3.9 0 TD
+0 Tc
+0 Tw
+(.)Tj
+/F3 1 Tf
+-18.74 -2.86 TD
+0.008 Tc
+-0.006 Tw
+[(Fi)6(gur)17(e )20(5 D)10(e)4(v)24(o)-1(l)6(u)-1(t)21(i)6(on)19( an)19(d P)15(ubl)26(i)6(c)4( G)6(o)19(od)19(s)]TJ
+ET
+0 0 0 RG
+0 J 0 j 2.16 w 10 M []0 d
+1 i
+402.96 494.48 144 -21.84 re
+S
+BT
+/F5 1 Tf
+12 0 0 12 415.68 481.04 Tm
+0.003 Tc
+-0.001 Tw
+[(S)-10(ubj)5(ecti)5(ve i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)]TJ
+ET
+402.96 436.88 57.6 -21.84 re
+S
+BT
+12 0 0 12 409.92 423.44 Tm
+0.004 Tc
+[(B)-9(enefi)6(t)2(s)]TJ
+ET
+316.56 537.68 72 -50.64 re
+S
+BT
+12 0 0 12 327.36 524.24 Tm
+0 Tc
+[(Ob)-4(je)-4(ctive)]TJ
+-0.42 -1.18 TD
+0.003 Tc
+[(Inform)16(ation)]TJ
+0.38 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(and S)-12(k)1(ills)]TJ
+ET
+1 J 1 j
+453.36 472.88 m
+438.96 436.88 l
+S
+BT
+12 0 0 12 108.72 446 Tm
+-0.001 Tc
+[(P)-14(o)-5(litica)-5(l)]TJ
+T*
+0.001 Tc
+(Decision)Tj
+ET
+0.72 w
+165 440.48 m
+165 440.48 l
+165 454.39 150.539 465.68 132.72 465.68 c
+114.901 465.68 100.44 454.39 100.44 440.48 c
+100.44 426.57 114.901 415.28 132.72 415.28 c
+150.539 415.28 165 426.57 165 440.48 c
+h
+165.36 429.68 m
+402.96 429.68 l
+S
+BT
+9.84 0 0 9.84 202.32 433.39 Tm
+0.006 Tc
+0.009 Tw
+[(Dec)-6(i)8(s)-6(i)8(ons)-6( ref)16(l)8(ec)-6(t)-9( )25(s)-6(o)1(c)-6(i)8(al)8( pref)16(erenc)-6(es)]TJ
+12 0 0 12 245.52 316.4 Tm
+-0.001 Tc
+[(Co)-5(st)]TJ
+T*
+0.004 Tc
+[(B)-9(ear)17(i)6(n)]TJ
+ET
+q
+245.52 300.8 48.48 27.12 re
+W n
+BT
+12 0 0 12 280.322 302.48 Tm
+0 Tc
+0 Tw
+(g)Tj
+ET
+Q
+301.8 310.88 m
+301.8 310.88 l
+301.8 324.79 285.726 336.08 265.92 336.08 c
+246.114 336.08 230.04 324.79 230.04 310.88 c
+230.04 296.97 246.114 285.68 265.92 285.68 c
+285.726 285.68 301.8 296.97 301.8 310.88 c
+h
+251.76 336.08 m
+165.36 422.48 l
+S
+BT
+9.84 0 0 9.84 108.72 390.19 Tm
+0.002 Tc
+[(A)-14(c)-10(c)-10(ount)12(abilit)-13(y)]TJ
+0 -1.2195 TD
+0.006 Tc
+-0.016 Tw
+[(t)-9(o)1( t)-9(a)1(x)-6( pay)-6(ers)]TJ
+2.9268 -2.439 TD
+0.473 Tw
+[(A)-11(v)-7(oi)7(d \223unf)-10(unded)]TJ
+0 -1.2195 TD
+[(m)-16(andat)15(es)-7(\224)]TJ
+ET
+410.16 415.28 m
+294.96 328.88 l
+S
+BT
+9.84 0 0 9.84 367.92 368.59 Tm
+-0.015 Tw
+[(F)-18(i)7(s)-7(c)-7(a)0(l)7( E)-11(qui)7(v)-7(a)0(l)7(enc)-7(e)]TJ
+T*
+0.009 Tw
+[(No redi)8(s)-6(t)16(ri)8(but)-9(i)8(o)1(n)]TJ
+12 0 0 12 166.32 590 Tm
+0.004 Tc
+[(Impl)6(em)17(entati)6(o)0(n)]TJ
+ET
+251.4 595.28 m
+251.4 595.28 l
+251.4 607.203 230.487 616.88 204.72 616.88 c
+178.953 616.88 158.04 607.203 158.04 595.28 c
+158.04 583.357 178.953 573.68 204.72 573.68 c
+230.487 573.68 251.4 583.357 251.4 595.28 c
+h
+244.56 580.88 m
+323.76 537.68 l
+251.76 602.48 m
+410.16 580.88 l
+S
+BT
+9.84 0 0 9.84 303.12 555.79 Tm
+0.005 Tc
+0.01 Tw
+[(E)-11(f)15(f)-10(i)7(c)-7(i)7(ent)15( P)13(r)-3(ov)-7(i)7(s)-7(i)7(o)0(n)]TJ
+ET
+215.52 573.92 m
+216 573.44 l
+215.28 572.72 l
+214.8 573.2 l
+215.52 573.92 l
+f*
+213.84 571.52 m
+214.32 571.28 l
+213.6 570.32 l
+213.12 570.8 l
+213.84 571.52 l
+f*
+212.16 569.12 m
+212.64 568.88 l
+211.92 568.16 l
+211.44 568.4 l
+212.16 569.12 l
+f*
+210.24 566.72 m
+210.72 566.48 l
+210.24 565.76 l
+209.76 566 l
+210.24 566.72 l
+f*
+208.56 564.56 m
+209.04 564.32 l
+208.56 563.36 l
+208.08 563.84 l
+208.56 564.56 l
+f*
+206.88 562.16 m
+207.36 561.92 l
+206.88 561.2 l
+206.4 561.44 l
+206.88 562.16 l
+f*
+205.2 560 m
+205.68 559.52 l
+205.2 558.8 l
+204.72 559.04 l
+205.2 560 l
+f*
+203.52 557.6 m
+204 557.12 l
+203.52 556.4 l
+203.04 556.88 l
+203.52 557.6 l
+f*
+201.84 555.2 m
+202.32 554.96 l
+201.84 554.24 l
+201.36 554.48 l
+201.84 555.2 l
+f*
+200.16 553.04 m
+200.64 552.56 l
+199.92 551.84 l
+199.44 552.08 l
+200.16 553.04 l
+f*
+198.48 550.64 m
+198.96 550.16 l
+198.24 549.44 l
+197.76 549.92 l
+198.48 550.64 l
+f*
+196.8 548.24 m
+197.28 548 l
+196.56 547.04 l
+196.08 547.52 l
+196.8 548.24 l
+f*
+195.12 546.08 m
+195.6 545.6 l
+194.88 544.88 l
+194.4 545.12 l
+195.12 546.08 l
+f*
+193.2 543.68 m
+193.68 543.2 l
+193.2 542.48 l
+192.72 542.96 l
+193.2 543.68 l
+f*
+191.52 541.28 m
+192 541.04 l
+191.52 540.08 l
+191.04 540.56 l
+191.52 541.28 l
+f*
+189.84 538.88 m
+190.32 538.64 l
+189.84 537.92 l
+189.36 538.16 l
+189.84 538.88 l
+f*
+188.16 536.72 m
+188.64 536.24 l
+188.16 535.52 l
+187.68 536 l
+188.16 536.72 l
+f*
+186.48 534.32 m
+186.96 534.08 l
+186.48 533.12 l
+186 533.36 l
+186.48 534.32 l
+f*
+184.8 531.92 m
+185.28 531.68 l
+184.8 530.96 l
+184.32 531.2 l
+184.8 531.92 l
+f*
+183.12 529.76 m
+183.6 529.28 l
+182.88 528.56 l
+182.4 528.8 l
+183.12 529.76 l
+f*
+181.44 527.36 m
+181.92 527.12 l
+181.2 526.16 l
+180.72 526.64 l
+181.44 527.36 l
+f*
+179.76 524.96 m
+180.24 524.72 l
+179.52 524 l
+179.04 524.24 l
+179.76 524.96 l
+f*
+177.84 522.56 m
+178.32 522.32 l
+177.84 521.6 l
+177.36 521.84 l
+177.84 522.56 l
+f*
+176.16 520.4 m
+176.64 519.92 l
+176.16 519.2 l
+175.68 519.68 l
+176.16 520.4 l
+f*
+174.48 518 m
+174.96 517.76 l
+174.48 517.04 l
+174 517.28 l
+174.48 518 l
+f*
+172.8 515.84 m
+173.28 515.36 l
+172.8 514.64 l
+172.32 514.88 l
+172.8 515.84 l
+f*
+171.12 513.44 m
+171.6 512.96 l
+171.12 512.24 l
+170.64 512.72 l
+171.12 513.44 l
+f*
+169.44 511.04 m
+169.92 510.8 l
+169.44 509.84 l
+168.96 510.08 l
+169.44 511.04 l
+f*
+167.76 508.88 m
+168.24 508.4 l
+167.52 507.68 l
+167.04 507.92 l
+167.76 508.88 l
+f*
+166.08 506.48 m
+166.56 506 l
+165.84 505.28 l
+165.36 505.76 l
+166.08 506.48 l
+f*
+164.4 504.08 m
+164.88 503.84 l
+164.16 502.88 l
+163.68 503.36 l
+164.4 504.08 l
+f*
+162.72 501.68 m
+163.2 501.44 l
+162.48 500.72 l
+162 500.96 l
+162.72 501.68 l
+f*
+160.8 499.52 m
+161.28 499.04 l
+160.8 498.32 l
+160.32 498.8 l
+160.8 499.52 l
+f*
+159.12 497.12 m
+159.6 496.88 l
+159.12 495.92 l
+158.64 496.4 l
+159.12 497.12 l
+f*
+157.44 494.72 m
+157.92 494.48 l
+157.44 493.76 l
+156.96 494 l
+157.44 494.72 l
+f*
+155.76 492.56 m
+156.24 492.08 l
+155.76 491.36 l
+155.28 491.84 l
+155.76 492.56 l
+f*
+154.08 490.16 m
+154.56 489.92 l
+154.08 488.96 l
+153.6 489.44 l
+154.08 490.16 l
+f*
+152.4 487.76 m
+152.88 487.52 l
+152.4 486.8 l
+151.92 487.04 l
+152.4 487.76 l
+f*
+150.72 485.6 m
+151.2 485.12 l
+150.48 484.4 l
+150 484.64 l
+150.72 485.6 l
+f*
+149.04 483.2 m
+149.52 482.72 l
+148.8 482 l
+148.32 482.48 l
+149.04 483.2 l
+f*
+147.36 480.8 m
+147.84 480.56 l
+147.12 479.84 l
+146.64 480.08 l
+147.36 480.8 l
+f*
+145.68 478.64 m
+146.16 478.16 l
+145.44 477.44 l
+144.96 477.68 l
+145.68 478.64 l
+f*
+143.76 476.24 m
+144.24 475.76 l
+143.76 475.04 l
+143.28 475.52 l
+143.76 476.24 l
+f*
+142.08 473.84 m
+142.56 473.6 l
+142.08 472.88 l
+141.6 473.12 l
+142.08 473.84 l
+f*
+140.4 471.68 m
+140.88 471.2 l
+140.4 470.48 l
+139.92 470.72 l
+140.4 471.68 l
+f*
+138.72 469.28 m
+139.2 468.8 l
+138.72 468.08 l
+138.24 468.56 l
+138.72 469.28 l
+f*
+137.04 466.88 m
+137.52 466.64 l
+137.04 465.68 l
+136.56 466.16 l
+137.04 466.88 l
+f*
+BT
+9.84 0 0 9.84 144.72 541.39 Tm
+[(S)-11(eparabl)7(e?)]TJ
+ET
+0.96 w
+316.56 494.48 m
+165.36 451.28 l
+S
+BT
+9.84 0 0 9.84 166.32 490.99 Tm
+0.015 Tc
+[(In)10(f)25(o)10(r)7(m)-6(e)10(d)]TJ
+T*
+0.005 Tc
+[(dec)-7(i)7(s)-7(i)7(on m)9(a)0(k)-7(i)7(ng)]TJ
+3.6585 -6.0976 TD
+-0.016 Tw
+[(A)-10(v)-6(oi)8(d i)8(n)1(t)-9(e)1(rj)8(uri)8(s)-6(di)8(c)-6(t)16(i)8(onal)8( )-25(ex)-6(t)16(e)1(rnal)8(i)8(t)-9(i)8(e)1(s)]TJ
+ET
+0 J 0 j 2.16 w
+410.16 588.08 129.6 -36.24 re
+S
+BT
+12 0 0 12 430.8 574.64 Tm
+0.001 Tc
+0.001 Tw
+[(P)-12(h)-3(ysical E)8(ffects:)]TJ
+-1.32 -1.18 TD
+0.004 Tc
+-0.002 Tw
+[(Moni)6(tor)17(i)6(ng Inform)17(ati)6(o)0(n)]TJ
+ET
+99.36 617.84 0.72 -0.72 re
+f*
+99.36 617.84 0.72 -0.72 re
+f*
+100.08 617.84 447.84 -0.72 re
+f*
+547.92 617.84 0.72 -0.72 re
+f*
+547.92 617.84 0.72 -0.72 re
+f*
+99.36 617.12 0.72 -331.92 re
+f*
+547.92 617.12 0.72 -331.92 re
+f*
+99.36 285.2 0.72 -0.72 re
+f*
+99.36 285.2 0.72 -0.72 re
+f*
+100.08 285.2 447.84 -0.72 re
+f*
+547.92 285.2 0.72 -0.72 re
+f*
+547.92 285.2 0.72 -0.72 re
+f*
+BT
+12 0 0 12 99.36 259.28 Tm
+0.003 Tc
+-0.001 Tw
+[(The fr)16(amew)5(o)19(r)-4(k can b)19(e)-1( used)19( i)5(n)-1( )-20(sever)16(a)-1(l)5( )-20(w)5(a)-1(ys. )-20( )-20(T)14(he )-20(fi)5(rs)23(t )-20(i)5(s)3( )-20(to )-20(an)19(al)5(yse )-20(the)19( )-20(sourc)23(e)-1(s)]TJ
+0 -1.14 TD
+0.159 Tw
+[(of success an)19(d fai)5(l)5(u)-1(r)16(e)-1( i)5(n)-1( cur)16(r)-4(ent )20(pol)5(i)5(c)3(i)5(e)-1(s. F)14(o)-1(r a )20(parti)5(cul)25(a)-1(r )-20(i)5(ssue,)21( )-20(i)5(denti)5(f)1(y )-20(t)21(h)-1(e)]TJ
+0 -1.16 TD
+0.019 Tw
+[(l)5(o)-1(cati)5(on of b)19(enefi)5(t)1(s, )20(and th)19(e l)5(o)-1(cati)5(on)19( and i)25(m)-4(port)21(ance )-20(of)21( )-20(subj)5(ecti)5(ve and )-20(obj)25(ecti)5(ve)]TJ
+T*
+0 Tc
+0.202 Tw
+[(in)-4(fo)-4(r)-7(m)-7(a)-4(ti)22(o)-4(n)-4( )20(a)-4(n)-4(d)16( )20(skills. T)-9(h)-4(e)16(n)-4( fr)-7(o)16(m)-7( th)-4(e)-4( )20(p)-4(o)-4(licy, id)-4(e)-4(n)16(tify th)-4(e)-4( lo)-4(c)20(a)-4(tio)-4(n)-4( o)-4(f)18( p)-4(o)-4(litica)-4(l)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(deci)5(s)3(i)5(ons, )20(i)5(m)-4(pl)5(e)19(m)-4(enta)19(t)1(i)5(on, )20(a)19(nd )20(cost b)19(eari)5(n)19(g. D)5(r)-4(aw)5( l)5(i)5(n)19(es betw)5(e)-1(e)19(n)-1( the )20(nodes)]TJ
+T*
+-0.001 Tw
+[(w)5(here the)19( l)5(o)-1(cati)5(on i)5(s)3( )20(the sa)19(me. )20(The l)5(i)5(nes i)25(ndi)5(cate t)21(he adva)19(n)-1(tages)23( of the)19( )-20(curr)16(ent)]TJ
+0 -1.14 TD
+0.259 Tw
+[(pol)5(i)5(cy )20(structu)19(r)-4(e. )20( )20(W)7(h)-1(e)19(r)-4(e )20(l)5(i)5(nes )40(do not c)23(onnect)21( nodes,)21( w)5(e)-1( mi)5(gh)19(t expect )20(that)]TJ
+0 -1.16 TD
+0.42 Tw
+[(pr)-5(oblem)-5(s)22( will ar)-5(ise. We c)22(an )-20(com)15(par)-5(e these pr)-5(edict)20(ed )-20(adva)18(n)-2(tages and)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(probl)6(ems)24( w)6(i)6(t)2(h obse)20(r)-3(vabl)6(e )20(experi)6(e)20(nce.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.039 Tw
+[(The )20(seco)19(nd )20(use )20(w)25(oul)5(d )20(be )40(to )20(desi)5(g)19(n )20(new)5( p)19(o)-1(l)5(i)5(cy structu)19(r)-4(es. H)5(e)19(re w)5(e)-1( w)5(o)19(ul)5(d star)16(t)]TJ
+0 -1.14 TD
+0.079 Tw
+[(w)5(i)5(t)1(h the i)5(ssue)19(-)-4(speci)5(f)1(i)5(c)3( l)5(o)-1(cati)5(o)19(n)-1( of b)19(enefi)5(t)1(s a)19(nd i)5(n)-1(fo)19(rmati)5(o)19(n)-1(, and)19( the i)5(m)16(port)21(ance)]TJ
+0 -1.16 TD
+0.059 Tw
+[(of di)5(ffere)19(nt types)23( of i)5(n)-1(fo)19(rmati)5(o)19(n)-1(, and)19( then try )-20(to )-20(c)23(hoose )-20(t)21(he )-20(opti)25(m)-4(al)5( )-20(l)5(o)-1(cati)5(o)19(n)-1( )-20(for)]TJ
+ET
+endstream endobj 220 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 221 0 obj << /Type /Page /Parent 224 0 R /Resources 223 0 R /Contents 222 0 R >> endobj 222 0 obj << /Length 6400 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(40)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.059 Tw
+[(each bub)19(bl)5(e, maki)25(ng tra)19(deoffs )20(betw)5(een)19( the )20(matches t)21(hat a)19(r)-4(e )-20(fo)19(rmed.)21( )-20( )-20(In )-20(so)19(me)]TJ
+0 -1.16 TD
+0 Tc
+0.062 Tw
+[(ca)-4(se)-4(s, wh)-4(e)-4(r)13(e)-4( n)-4(o)-4( o)16(b)-4(je)-4(ctive)-4( in)-4(fo)16(r)-7(m)-7(a)-4(tio)16(n)-4( o)-4(r)-7( s)20(p)-4(e)-4(c)0(ia)-4(lise)-4(d)-4( skills a)16(r)-7(e)-4( r)13(e)-4(le)-4(va)-4(n)-4(t, o)-4(r)-7( )-20(th)16(e)-4(y)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(are hel)5(d i)25(n)-1( the s)23(a)-1(me l)5(o)-1(ca)19(ti)5(on as t)21(he be)19(nefi)5(t)1(s, al)5(l)5( n)19(odes ca)19(n )-20(have )-20(t)21(he )-20(sa)19(me)]TJ
+T*
+0.199 Tw
+[(l)5(o)-1(cati)5(on )20(and)19( )20(no )20(con)19(f)1(l)5(i)5(c)3(t ari)5(s)3(es. )20( S)10(ubdi)5(vi)5(si)5(on i)5(s)3( an)19( exam)16(pl)5(e of thi)5(s)23(. In ot)21(her)]TJ
+0 -1.14 TD
+0.12 Tw
+[(cases, effects )20(ar)-5(e loc)22(a)-2(l but i)24(m)-5(por)-5(t)20(ant obj)24(ective )-20(info)18(r)-5(m)-5(a)-2(tio)18(n)-2( )-20(and )-20(skills )-20(a)18(r)-5(e )-20(hel)24(d)]TJ
+0 -1.16 TD
+0.659 Tw
+[(central)5(l)5(y)3(. H)5(e)19(re confl)5(i)5(c)3(t )20(ari)5(s)3(es i)5(n)-1( c)23(hoi)5(ce of)21( )-20(i)5(m)-4(pl)5(em)16(entati)5(o)19(n )-20(l)5(o)-1(cati)5(on)19(.)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(A)11(l)6(ternati)6(v)4(el)6(y, i)6(m)-3(pl)26(ement)22(ati)6(on i)6(s)4( i)6(d)0(e)20(a)0(l)6(l)6(y)4( nati)6(o)0(n)20(a)0(l)6(,)2( but )20(pol)6(i)6(t)2(i)6(c)4(al)6( deci)6(s)4(i)6(on )20(maki)6(ng )-20(i)6(s)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(i)5(deal)5(l)5(y)3( )20(l)5(o)-1(cal)5( )20(\(o)19(r vi)5(ce ve)19(rsa\), )20(and th)19(ey are)19( di)5(ffi)5(cul)5(t)1( to )20(decoupl)25(e. T)14(he deci)5(s)3(i)5(o)-1(n)19( on)]TJ
+T*
+0.119 Tw
+[(how)5( to deal)5( w)5(i)5(t)21(h thi)5(s)3( confl)5(i)5(c)3(t)21( feeds t)21(h)-1(rou)19(gh to )-20(th)19(e )-20(choi)5(ce)19( )-20(of )-20(l)5(o)-1(cati)25(ons )-20(for)16( )-20(cost)]TJ
+0 -1.14 TD
+[(beari)5(ng. )20( A)10(n)-1( exam)16(pl)5(e of thi)5(s)3( si)5(t)21(uati)5(on i)5(s)3( )20(di)5(scussed i)5(n)-1( )20(depth i)25(n)-1( the )-20(c)23(o)-1(mpani)25(on)]TJ
+0 -1.16 TD
+0 Tw
+[(paper)-5( )20(\()-5(W)6(P)9( 98/7a\))15( on kiwi ha)18(bitat.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.038 Tw
+[(The )20(thi)26(r)-3(d )20(use )40(ari)6(s)4(es )20(w)6(h)0(e)20(n)0( )20(the)20(r)-3(e )20(ar)17(e unav)24(oi)6(dabl)6(e c)24(onfl)6(i)6(c)4(ts i)6(n)0( choi)6(c)24(e)0( of \221)6(l)6(o)0(cati)26(on\222)6(.)]TJ
+0 -1.16 TD
+0.003 Tc
+0.179 Tw
+[(If )20(a l)5(i)5(n)-1(k cann)19(ot be ac)23(hi)5(eved, )20(a pro)19(b)-1(l)5(e)-1(m a)19(r)-4(i)5(s)3(es. A)10(l)5(ter)16(nati)5(v)3(e a)19(ppro)19(a)-1(ches m)16(a)-1(y)]TJ
+0 -1.14 TD
+0.259 Tw
+[(exi)5(s)3(t for achi)25(evi)5(ng th)19(e bene)19(fi)5(t that t)21(he m)16(a)-1(tch betw)25(een l)5(e)-1(vel)5(s)3( )20(of j)5(u)-1(ri)5(sdi)5(c)3(ti)25(on)]TJ
+0 -1.16 TD
+0.34 Tw
+[(achieves. )20( )20(If, )20(for ex)22(ample,)20( implem)15(entatio)18(n is local bu)18(t ther)15(e is significan)18(t)]TJ
+T*
+0.18 Tw
+[(objective )20(info)18(r)-5(m)-5(a)-2(tio)18(n)-2( )20(and )40(need )20(f)20(o)-2(r)-5( )20(spe)18(c)2(ialised skills which a)18(r)-5(e held)18( centr)15(a)-2(lly,)]TJ
+T*
+0.119 Tw
+[(provi)5(s)3(i)5(on )20(m)16(a)-1(y )20(be )20(i)5(n)19(effi)5(ci)5(ent. )20( )20(If w)5(e)-1( dev)23(el)5(op effe)19(cti)5(v)3(e me)19(ans of c)23(o)-1(mm)16(uni)5(cati)5(on)]TJ
+T*
+0.019 Tw
+[(betw)5(een ce)19(ntral)5( i)5(n)-1(f)21(o)-1(rm)16(ati)5(on hol)25(ders a)19(nd l)5(o)-1(cal)5( i)25(m)-4(pl)5(eme)19(n)-1(ters, )20(thi)5(s)3( confl)5(i)5(c)3(t )-20(c)23(an )-20(be)]TJ
+0 -1.14 TD
+0.004 Tc
+(reduced.)Tj
+0 -2.32 TD
+0.003 Tc
+0.079 Tw
+[(The m)16(enu of l)25(o)-1(cati)5(onal)5( c)23(hoi)5(ces fo)19(r the c)23(hoi)5(ce no)19(des i)5(s)3( l)5(i)5(m)-4(i)5(t)1(e)19(d)-1( i)5(n)-1( re)19(al)5(i)5(t)1(y by )-20(ou)19(r)]TJ
+0 -1.16 TD
+0.179 Tw
+[(exi)5(s)3(ti)5(ng )20(struct)21(ures o)19(f)1( gove)19(r)-4(nme)19(n)-1(t. W)7(e)-1( d)19(o)-1( not ha)19(ve sep)19(a)-1(rate)19( gove)19(r)-4(nme)19(n)-1(t or)]TJ
+T*
+0.039 Tw
+[(even sepa)19(rate l)5(a)-1(w)5(s)3(,)21( for e)19(v)3(ery i)5(ssue)19(,)1( so i)5(t)1( i)5(s)3( r)16(a)-1(re t)21(hat )-20(th)19(e )-20(are)19(a)-1( )-20(of )-20(ef)21(fects )-20(exactl)5(y)]TJ
+0 -1.14 TD
+0.019 Tw
+[(matches th)19(e j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( of p)19(o)-1(l)5(i)5(t)1(i)5(c)3(al)5( deci)5(s)3(i)5(on )20(maki)5(ng or )-20(th)19(e )-20(are)19(a)-1( )-20(w)5(her)16(e )-20(costs )-20(a)19(r)-4(e)]TJ
+0 -1.18 TD
+0.099 Tw
+[(borne. )20(Most d)19(e)-1(ci)5(si)5(ons a)19(r)-4(e a co)19(mpro)19(mi)5(se a)19(m)-4(ong v)23(a)-1(ri)5(ous c)23(oncer)16(ns. )]TJ
+/F3 1 Tf
+31.42 0 TD
+0.008 Tc
+0.114 Tw
+[(Fi)26(gur)17(e 5)]TJ
+/F5 1 Tf
+-31.42 -1.18 TD
+0.003 Tc
+-0.001 Tw
+[(hel)5(ps cl)5(ari)5(f)1(y t)21(he necess)23(a)-1(ry ch)19(oi)5(ces and )20(the t)21(r)-4(adeof)21(fs.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.098 Tw
+[(To )20(thi)6(s)4( )20(poi)26(nt w)6(e)0( hav)24(e l)6(ooked)20( at the)20( choi)6(ce o)20(f)2( l)6(e)0(vel)6( of )20(gover)17(nment)22( for di)6(f)22(f)2(ere)20(n)0(t)]TJ
+0 -1.16 TD
+0 Tc
+0.062 Tw
+[(fu)-4(n)-4(c)0(tio)-4(n)-4(s)0( )20(in)-4( )20(t)18(e)-4(r)-7(m)-7(s)0( )40(o)-4(f)-2( )20(fu)-4(n)-4(d)16(a)-4(m)-7(e)-4(n)16(ta)-4(l ch)-4(a)16(r)-7(a)-4(c)0(te)-4(r)-7(i)2(stics )20(o)-4(f)-2( th)-4(e)-4( iss)20(u)-4(e)-4( a)-4(n)16(d)-4( th)-4(e)-4( ca)16(p)-4(a)-4(b)-4(ility)]TJ
+T*
+0.003 Tc
+0.119 Tw
+[(of j)5(u)-1(ri)5(sdi)5(c)3(ti)5(ons.)21( W)7(e)-1( have i)25(m)-4(pl)5(i)5(c)3(i)5(t)1(l)5(y)3( assu)19(med th)19(at each )-20(l)25(e)-1(vel)5( )-20(of )-20(g)19(o)-1(vern)19(ment )-20(i)5(s)]TJ
+T*
+0.019 Tw
+[(equal)5(l)5(y)3( )20(accou)19(n)-1(tabl)5(e )20(b)19(o)-1(th i)5(n)-1( t)21(e)-1(rms )20(of soci)5(al)5( d)19(e)-1(ci)5(si)5(on maki)25(ng and)19( for )20(effi)5(ci)5(ency of)]TJ
+0 -1.14 TD
+0.379 Tw
+[(i)5(m)-4(pl)5(ement)21(ati)5(on. I)21(n)-1( addi)5(ti)25(on w)5(e)-1( hav)23(e onl)5(y co)19(ncern)19(ed )-20(ou)19(rsel)5(ves )-20(w)5(i)5(t)1(h )-20(t)21(h)-1(e)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(outcomes )20(of the )20(pol)5(i)5(t)1(i)5(c)3(al)5( pr)16(ocess not)21( the )-20(p)19(r)-4(ocess )-20(i)5(t)1(sel)5(f)21(. )-20( )-20(R)5(e)-1(l)5(a)-1(xi)5(ng ei)5(ther of )-20(thes)23(e)]TJ
+T*
+[(constrai)5(nts )20(mi)5(ght al)5(t)21(e)-1(r o)19(u)-1(r concl)25(u)-1(si)5(ons.)]TJ
+ET
+endstream endobj 223 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 224 0 obj << /Type /Pages /Kids [ 221 0 R 89 0 R 227 0 R 91 0 R 232 0 R 235 0 R 238 0 R 96 0 R 100 0 R 103 0 R ] /Count 10 /Parent 151 0 R >> endobj 225 0 obj << /Length 7420 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(41)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+-0.001 Tc
+0.003 Tw
+[(6)-1805(ACCOUNT)-10(ABIL)-10(I)-3(T)-10(Y)6( OF)-10( )21(GOVERNM)-8(ENT)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.003 Tc
+0.119 Tw
+[(E)10(v)3(en w)5(here b)19(enefi)5(t)1(s, cos)23(t)1(s and )20(deci)5(s)3(i)5(ons a)19(r)-4(e al)5(l)5( al)5(i)5(g)19(ned soci)5(al)5( deci)5(s)3(i)5(ons )-20(a)19(n)-1(d)]TJ
+0 -1.14 TD
+0.004 Tc
+0.058 Tw
+[(i)6(m)-3(pl)6(ement)22(ati)6(on )40(may )20(be )40(poor )20(i)6(f)22( the g)20(o)0(vern)20(ment st)22(ructu)20(r)-3(e i)6(s)4( i)6(nhe)20(rentl)6(y)4( i)6(n)20(effi)6(ci)6(ent)]TJ
+0 -1.16 TD
+0.002 Tc
+0.36 Tw
+[(or)-5( unacco)18(untabl)24(e. B)9(o)-2(th local )20(and ce)18(ntr)-5(a)-2(l g)18(o)-2(ver)-5(n)18(m)-5(ent f)20(a)-2(ce acco)18(untability)]TJ
+T*
+0.099 Tw
+[(probl)5(ems)23(.)1( If l)5(o)-1(cal)5( g)19(o)-1(vern)19(ment i)5(s)3( c)23(onsi)5(d)-1(e)19(r)-4(ed to )20(be )-20(l)5(e)-1(ss )-20(acc)23(ounta)19(b)-1(l)5(e)-1(, )-20(i)5(t)1( )-20(may)23( )-20(be)]TJ
+T*
+-0.001 Tw
+[(w)5(o)-1(rth tr)16(adi)5(ng of)21(f the h)19(e)-1(ter)16(ogenei)5(ty )20(of l)5(o)-1(cal)5( d)19(e)-1(ci)5(si)5(ons, o)19(r)-4( the )20(benefi)5(t)1(s )20(of )-20(bal)5(an)19(ced)]TJ
+T*
+0.04 Tw
+[(decision m)-5(a)-2(kin)18(g)-2( for)-5( i)24(m)-5(pr)15(oved political )20(accounta)18(b)-2(ility by m)15(a)-2(king decisio)18(ns at )-20(th)18(e)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(nati)5(onal)5( l)5(e)-1(vel)5(.)]TJ
+0 -2.32 TD
+0.039 Tw
+[(Governm)16(ents a)19(r)-4(e ul)5(ti)5(m)16(a)-1(tel)5(y)3( acco)19(untabl)5(e )20(to vote)19(rs. C)5(onsti)5(t)21(uents )-20(v)23(o)-1(te )-20(bas)23(ed )-20(on)]TJ
+0 -1.16 TD
+0.001 Tc
+0.161 Tw
+[(their)-6( )20(pr)14(efer)-6(e)17(n)-3(ces, th)17(eir)-6( belie)17(fs abou)17(t what )20(M)-6(P)8(s/councillor)-6(s)1(/p)17(olitical par)14(ties will)]TJ
+T*
+0.003 Tc
+0.379 Tw
+[(do, )20(and )20(t)21(hei)5(r )20(o)19(b)-1(servati)25(ons ab)19(out the)19( outpu)19(ts and )20(outcom)16(e)-1(s achi)5(ev)23(ed by)]TJ
+0 -1.14 TD
+[(govern)19(m)-4(ent. )20(To th)19(e l)5(i)5(m)-4(i)5(t)1(ed )20(extent t)21(hat voti)5(n)19(g)-1( refl)25(ects )-20(past outputs)23( )-20(and)]TJ
+0 -1.16 TD
+0.079 Tw
+[(outcomes, i)25(ndi)5(vi)5(dual)5(s a)19(nd gov)23(ernm)16(ents a)19(r)-4(e acco)19(untabl)5(e)19( for t)21(hese. )20(Medi)5(a a)19(n)-1(d)]TJ
+T*
+[(ci)5(ti)5(zen w)5(a)-1(tchdog)19( gro)19(ups may)23( be abl)25(e to m)16(a)-1(ke )-20(the)19(m)-4( )-20(mo)19(re )-20(di)25(rectl)5(y)3( )-20(acco)19(untabl)5(e)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(for pa)20(rti)6(c)4(ul)6(ar )20(outputs )20(and o)20(u)0(tcomes)24( by maki)26(ng thes)24(e tra)20(n)0(spare)20(n)0(t.)]TJ
+12 0 2.551 12 99.36 497.84 Tm
+0.002 Tc
+0 Tw
+[(Local Gover)15(n)-2(m)-5(e)-2(n)18(t)0( A)9(ccountability A)9(d)-2(va)18(ntages)]TJ
+12 0 0 12 99.36 470 Tm
+0.039 Tw
+[(In )20(some )20(w)5(a)-1(ys)23( )20(the p)19(r)-4(obl)5(e)19(m)-4(s fro)19(m)-4( poo)19(r publ)5(i)5(c)3( ch)19(oi)5(ce m)16(e)-1(chani)5(sms)23( red)19(u)-1(ce as th)19(e)]TJ
+T*
+0.219 Tw
+[(scope )20(and )20(si)5(z)23(e)-1( )20(of th)19(e j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1( fal)5(l)5(s)3(. V)10(o)-1(te)19(rs expr)16(ess thei)25(r i)5(n)-1(ter)16(e)-1(sts mo)19(re)]TJ
+T*
+0.519 Tw
+[(di)5(rectl)5(y)3( w)5(hen )20(the vot)21(e)-1( i)5(s)3( over)16( a )-20(na)19(rrow)5( range )-20(o)19(f)1( )-20(i)5(ssues )-20(e)19(.)1(g.: )-20(w)5(a)-1(t)21(e)-1(r)]TJ
+0 -1.14 TD
+0.004 Tc
+0.498 Tw
+[(manage)20(ment. )20( A)11(s)4( prefe)20(r)-3(ences )20(becom)17(e mo)20(re ho)20(moge)20(nous w)6(i)6(t)2(h )-20(s)24(m)-3(al)6(l)6(e)0(r)]TJ
+0 -1.16 TD
+0.002 Tc
+0.04 Tw
+[(jur)-5(i)4(sdictions, voti)24(ng cycles, a)18(nd pr)15(oblem)-5(s ar)-5(ising )-20(f)20(r)-5(om)-5( differ)-5(e)18(nces )-20(in )-20(int)20(ensity )-20(of)]TJ
+T*
+0.199 Tw
+[(prefer)16(ence, )20(o)19(r)-4( )20(do)19(ubl)5(e )20(pe)19(aked )20(p)19(r)-4(efer)16(ences b)19(e)-1(come l)25(e)-1(ss seri)5(o)19(u)-1(s. T)14(a)-1(ki)5(ng the)]TJ
+T*
+0.239 Tw
+[(argum)16(ents fo)19(r i)5(m)-4(p)19(r)-4(ovi)5(ng p)19(r)-4(efe)19(r)-4(ence )20(repr)16(esentati)25(on to a)19(n)-1( extr)16(eme, )20(how)5(ever)16(,)]TJ
+T*
+0.004 Tc
+0.218 Tw
+[(each )20(i)6(ndi)6(vi)6(dual)6( )20(w)26(oul)6(d )20(ul)6(ti)6(m)17(a)0(tel)6(y)4( ne)20(ed to v)24(o)0(te fo)20(r a di)6(ff)22(erent )20(orga)20(ni)6(sati)6(on o)20(n)]TJ
+0 -1.14 TD
+0.003 Tc
+0.339 Tw
+[(each )20(i)5(ssue, )20(a)19(nd di)5(ffe)19(rent )20(orga)19(ni)5(sati)5(ons w)5(o)19(ul)5(d ope)19(rate f)21(o)-1(r e)19(a)-1(ch exte)19(rnal)5(i)5(t)1(y)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(bounda)19(ry. T)14(h)-1(i)5(s)3( i)5(s)3( cl)5(earl)5(y)3( u)19(n)-1(w)5(o)-1(rka)19(b)-1(l)5(e)-1(.)]TJ
+0 -2.32 TD
+0.14 Tw
+[(T)-7(he )20(lar)15(ger)-5( t)20(he nu)18(m)-5(ber)15( of ag)18(ents r)15(e)-2(sponsible )20(for)-5( co)18(ntr)-5(o)-2(lling)18( a given )20(r)-5(e)-2(sou)18(r)-5(ce,)]TJ
+0 -1.16 TD
+0.039 Tw
+[(the har)16(der i)5(t)1( i)5(s)3( t)21(o)-1( obse)19(r)-4(ve eac)23(h age)19(nt\222)5(s)3( )-20(effo)19(rt )-20(beca)19(u)-1(se )-20(th)19(e )-20(obse)19(r)-4(vabl)5(e resou)19(r)-4(ce)]TJ
+0 -1.14 TD
+0.004 Tc
+0.258 Tw
+[(outcome i)6(s)4( )20(a poo)20(r i)6(ndi)6(cat)22(o)0(r of t)22(he ag)20(ent\222)6(s)4( eff)22(o)0(rt. W)8(h)20(en i)6(n)0(fo)20(rmati)6(o)20(n)0( )-20(abou)20(t)]TJ
+0 -1.16 TD
+0.002 Tc
+0.24 Tw
+[(agents\222 )20(eff)20(o)-2(r)-5(t)0(s is p)18(oor)-5(, a)18(gents )20(ar)-5(e less )20(account)20(able. E)9(ffective )20(account)20(ability)]TJ
+T*
+0.279 Tw
+[(structur)16(es bal)5(anc)23(e the )20(ri)5(sk i)5(m)-4(pos)23(ed on )20(agents agai)5(nst )-20(t)21(he )-20(str)16(ength of )-20(the)]TJ
+T*
+0.139 Tw
+[(i)5(n)-1(centi)5(v)3(es they )20(face. If)21( the co)19(ntract i)5(s)3( )20(based o)19(n)-1( )-20(po)19(or )-20(i)5(n)-1(fo)19(rmati)25(on )-20(and)19( )-20(hence)]TJ
+T*
+0.12 Tw
+[(im)-5(poses )20(un)18(r)-5(easo)18(nable )40(r)-5(i)4(sks )20(on )20(ag)18(ents, )20(in )40(r)-5(eality th)18(e cont)20(r)-5(a)-2(ct will br)15(eak down)18(.)]TJ
+0 -1.14 TD
+0 Tc
+0.002 Tw
+[(T)-9(h)-4(e)-4(y)0( will n)-4(o)-4(t)-2( )20(b)-4(e)-4( h)-4(e)-4(l)2(d)-4( )20(r)-7(e)-4(sp)-4(o)16(n)-4(sib)-4(l)2(e)-4( fo)16(r)-7( o)-4(u)-4(t)-2(co)16(m)-7(e)-4(s cle)-4(a)16(r)-7(l)2(y b)-4(e)-4(y)0(o)16(n)-4(d)-4( th)-4(e)-4(i)22(r)-7( co)-4(n)-4(t)18(r)-7(o)-4(l.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.339 Tw
+[(The l)5(i)5(n)-1(k be)19(tw)5(een co)19(nsti)5(tuent)21( and a)19(gent i)5(s)3( cl)5(ose)19(r)-4( i)5(n)-1( l)5(o)-1(c)23(a)-1(l)5( )-20(than )-20(i)25(n)-1( )-20(cent)21(ral)]TJ
+0 -1.16 TD
+0.359 Tw
+[(govern)19(m)-4(ent. )20( )20(The l)5(o)-1(c)23(a)-1(l)5( consti)5(tu)19(ents can)19( mor)16(e)-1( easi)5(l)5(y)3( m)16(oni)5(tor )20(the a)19(gents\222)]TJ
+T*
+0.059 Tw
+[(provi)5(s)3(i)5(on )20(eff)21(o)-1(rts. )20( )20(The l)25(o)-1(cal)5( offi)5(ci)5(al)5( )20(may have)19( a re)19(asonabl)25(e l)5(e)-1(vel)5( of c)23(ontrol)5( )20(over)]TJ
+0 -1.14 TD
+0.319 Tw
+[(the l)5(o)-1(cal)5( outc)23(o)-1(mes, )20(parti)5(cul)25(a)-1(rl)5(y pr)16(ocess outc)23(o)-1(mes. )20( In cont)21(rast, i)5(n)19( centr)16(a)-1(l)]TJ
+0 -1.16 TD
+0.039 Tw
+[(govern)19(m)-4(ent, a)19(n)-1( i)5(ndi)5(vi)5(dual)25( offi)5(ci)5(al)5( i)5(s)3( pa)19(rt of )20(a much l)25(a)-1(rge)19(r)-4( bu)19(reauc)23(racy )-20(and)19( )-20(may)]TJ
+T*
+-0.001 Tw
+[(have l)5(e)-1(ss di)5(scr)16(eti)5(ona)19(ry pow)5(e)19(r)-4( and )20(hence l)5(e)-1(ss)23( contr)16(o)-1(l)5( over )20(outco)19(mes.)]TJ
+ET
+endstream endobj 226 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 227 0 obj << /Type /Page /Parent 224 0 R /Resources 229 0 R /Contents 228 0 R >> endobj 228 0 obj << /Length 8551 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(42)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.019 Tw
+[(To the )20(extent t)21(hat cons)23(ti)5(tuents )20(are )20(mobi)5(l)5(e)-1(, t)21(he )-20(exi)5(s)3(tenc)23(e )-20(of mul)5(t)1(i)5(p)-1(l)5(e)-1( )-20(j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.283 Tw
+[(will m)-8(a)-5(ke)-5( ju)-5(r)-8(i)1(sd)-5(ictio)-5(n)-5(s)19( co)-5(m)-8(p)15(e)-5(t)-3(e)-5( fo)15(r)-8( co)-5(n)-5(s)-1(titu)15(e)-5(n)-5(t)-3(s b)-5(y)-1( )20(p)-5(r)-8(o)-5(v)-1(id)-5(in)15(g)-5( g)-5(o)-5(o)15(d)-5( se)-5(r)-8(v)-1(ice)-5(s)]TJ
+T*
+0.002 Tc
+0.2 Tw
+[(m)-5(o)-2(r)-5(e)-2( )20(e)18(fficiently. )20( )20(T)-7(h)-2(is will lead to)18( downwa)18(r)-5(d pr)-5(e)18(ssur)-5(e)18( on costs )20(of pr)15(ovision.)]TJ
+T*
+0.099 Tw
+[(Local)5( gove)19(r)-4(nme)19(n)-1(ts may )20(be m)16(o)-1(re acc)23(ounta)19(b)-1(l)5(e)-1( to )-20(co)19(nsti)5(tuents becaus)23(e )-20(of )-20(th)19(ei)5(r)]TJ
+0 -1.14 TD
+0.199 Tw
+[(smal)5(l)5( si)5(ze, and)19( thei)5(r )20(need t)21(o)-1( comp)19(ete, b)19(u)-1(t l)5(e)-1(ss acco)19(untabl)5(e)19( )-20(i)5(f)1( )-20(l)5(o)-1(cal)5( )-20(pol)5(i)5(t)1(i)5(c)3(al)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(structur)16(es are)19( i)5(neffecti)5(v)3(e)19(.)]TJ
+0 -2.32 TD
+0.519 Tw
+[(Local)5( gove)19(r)-4(nme)19(n)-1(t i)5(s)3( al)5(so acc)23(ounta)19(b)-1(l)5(e)-1( to ce)19(ntral)5( g)19(o)-1(vern)19(ment. )20( )-20(C)5(entr)16(a)-1(l)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(govern)19(m)-4(ent d)19(e)-1(fi)5(nes th)19(e pow)5(e)19(r)-4(s of l)5(o)-1(cal)5( )20(govern)19(m)-4(ent)21( and co)19(nstrai)5(ns)23( thei)5(r acti)5(ons)]TJ
+0 -1.14 TD
+0.079 Tw
+[(through)19( )20(l)5(egi)5(sl)5(ati)5(on )40(enforc)23(eabl)5(e )40(by )20(the E)10(n)-1(vi)5(r)16(onme)19(n)-1(t C)5(our)16(t. To)19( a cer)16(t)1(ai)5(n exte)19(nt,)]TJ
+0 -1.16 TD
+0.039 Tw
+[(l)5(o)-1(cal)5( )20(govern)19(m)-4(ent i)5(s)3( )20(account)21(abl)5(e to c)23(entr)16(a)-1(l)5( gover)16(nmen)19(t becaus)23(e of t)21(he thr)16(eat of)]TJ
+T*
+0.019 Tw
+[(changes to)19( thei)5(r )20(pow)5(ers. )20( Local)5( g)19(o)-1(vern)19(ments m)16(a)-1(y tr)16(y to )-20(an)19(ti)5(ci)5(pate )-20(th)19(e )-20(conce)19(r)-4(ns)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(of central)6( )20(gover)17(nmen)20(t to mi)26(ni)6(mi)6(se thi)6(s)4( t)22(h)0(reat)22(.)]TJ
+12 0 2.551 12 99.36 551.84 Tm
+0.002 Tc
+0 Tw
+[(National Gove)18(r)-5(n)-2(m)-5(e)18(nt A)9(ccounta)18(b)-2(ility A)9(d)-2(vantages)]TJ
+12 0 0 12 99.36 524 Tm
+0.179 Tw
+[(In the ot)21(her di)25(recti)5(on, c)23(onsti)5(tue)19(n)-1(ts have)19( )-20(l)5(e)-1(ss )-20(cont)21(rol)5( )-20(ove)19(r)-4( )-20(a )-20(l)5(a)-1(r)16(ge )-20(nu)19(mbe)19(r)-4( )-20(of)]TJ
+T*
+0.319 Tw
+[(govern)19(m)-4(ents. A)10(s)3( th)19(e nu)19(mber )20(of or)16(gani)5(sati)5(ons )20(grow)5(s, )20(each o)19(ne ten)19(d)-1(s to)]TJ
+T*
+0.004 Tc
+0.438 Tw
+[(become l)6(e)0(ss)24( account)22(abl)6(e an)20(d mo)20(re )-20(abl)26(e )-20(to )-20(be )-20(m)17(ani)6(p)20(u)0(l)6(a)0(ted by )-20(speci)6(a)0(l)]TJ
+0 -1.24 TD
+0.001 Tc
+[(inter)-6(e)-3(sts.)]TJ
+10.08 0 0 10.08 148.08 484.285 Tm
+-0.008 Tc
+(20)Tj
+12 0 0 12 159.12 481.28 Tm
+0.003 Tc
+0.059 Tw
+[( )20( )20(C)5(onsti)5(tuen)19(ts )20(w)5(ho exp)19(r)-4(ess p)19(o)-1(l)5(i)5(t)1(i)5(c)3(al)5( pref)21(erenc)23(es bea)19(r costs o)19(f)1( doi)5(ng)]TJ
+-4.98 -1.16 TD
+0.199 Tw
+[(so. )20( )20(W)7(hen )20(an)19( )20(i)5(ssue )20(has )40(a )20(smal)5(l)5( i)25(m)-4(pact o)19(n)-1( a l)5(a)-1(r)16(ge nu)19(mber)16( of pe)19(opl)5(e, e)19(a)-1(ch)]TJ
+T*
+0.001 Tc
+0.081 Tw
+[(individual )20(will )20(tend )20(n)17(o)-3(t )20(to )40(get involve)17(d)-3(; i.e. th)17(ey will fr)-6(ee )20(r)-6(i)3(de o)17(n)-3( othe)17(r)-6(s)1(\222 political)]TJ
+T*
+-0.001 Tc
+0.443 Tw
+[(p)-5(a)-5(r)-8(ticip)-5(a)-5(t)-3(io)-5(n)15(.)-3( On)-5(ly co)15(n)-5(c)-1(e)-5(n)-5(t)-3(r)12(a)-5(te)-5(d)-5( in)-5(t)17(e)-5(r)-8(e)-5(sts will e)-5(x)19(p)-5(r)-8(e)-5(ss t)17(h)-5(e)-5(i)1(r)-8( p)15(r)-8(e)-5(f)-3(e)15(r)-8(e)-5(n)-5(c)-1(e)-5(s)-1(.)]TJ
+0 -1.14 TD
+0.063 Tw
+[(De)-5(cisio)-5(n)-5(s)-1( will b)-5(e)-5( se)-5(r)-8(i)1(o)15(u)-5(sly b)-5(i)1(a)-5(s)-1(e)-5(d)-5(.)-3( )20( In)-5( so)15(m)-8(e)-5( wa)-5(ys th)-5(is is )-20(w)21(h)-5(a)-5(t)-3( )-20(NZ)-10( m)-8(o)-5(ve)-5(d)-5( a)-5(w)1(a)-5(y)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(from w)6(i)6(t)2(h )20(Local)6( Gove)20(rnm)17(ent R)6(e)0(fo)20(rm.)]TJ
+0 -2.32 TD
+0.198 Tw
+[(C)6(entral)6( gov)24(ern)20(m)-3(ent i)6(s)4( a )20(mor)17(e)0( sophi)6(sti)6(c)4(a)20(t)2(ed i)6(n)0(sti)6(t)2(u)20(t)2(i)6(on w)6(i)6(t)2(h b)20(e)0(tter )20(resou)20(r)-3(ces,)]TJ
+0 -1.16 TD
+0 Tc
+0.042 Tw
+[(in)-4(clu)-4(d)-4(i)2(n)-4(g)-4( )20(in)-4(te)16(r)-7(n)-4(a)-4(l)2( a)-4(cco)16(u)-4(n)-4(t)-2(a)-4(b)-4(ility st)18(r)-7(u)-4(ctu)16(r)-7(e)-4(s)0(. )20(T)-9(h)-4(is m)-7(a)-4(y )20(g)-4(i)2(ve)-4( it so)16(m)-7(e)-4( a)-4(d)-4(v)0(a)16(n)-4(ta)-4(g)-4(e)16( in)]TJ
+0 -1.14 TD
+0.003 Tc
+0.099 Tw
+[(soci)5(al)5( )20(deci)5(s)3(i)5(on )20(m)16(a)-1(ki)5(ng )20(an)19(d )20(effi)5(ci)5(ent)21( )20(provi)5(s)3(i)5(o)19(n. It i)5(s)3( l)5(i)5(k)3(el)5(y t)21(o)-1( be )20(more )20(pol)5(i)5(t)1(i)5(c)3(al)5(l)5(y)]TJ
+0 -1.16 TD
+0.459 Tw
+[(accountabl)5(e)19(,)1( to th)19(e extent)21( )-20(that pol)5(i)5(t)1(i)5(c)3(al)5( )-20(pr)16(essure and )-20(l)5(o)-1(b)19(b)-1(yi)5(ng )-20(i)5(s)3( )-20(m)16(o)-1(re)]TJ
+T*
+0.319 Tw
+[(sophi)5(sti)5(c)3(ated )40(at )20(the )20(c)23(entral)5( )40(rath)19(er )20(tha)19(n)-1( l)5(o)-1(cal)5( l)5(e)-1(vel)5(.)21( Its di)5(sadv)23(antag)19(es are)]TJ
+T*
+0.1 Tw
+[(distance fr)15(om)-5( th)18(e affect)20(ed com)15(m)-5(unity, )20(and the)18( fact )-20(t)20(hat )-20(th)18(er)-5(e )-20(a)18(r)-5(e )-20(few m)-5(obility)]TJ
+T*
+0.06 Tw
+[(pr)-5(essur)15(e)-2(s on ce)18(ntr)-5(a)-2(l g)18(o)-2(ver)-5(n)18(m)-5(ent. )20( Dissatisfied vot)20(e)-2(r)-5(s)2( m)15(a)-2(y )-20(exp)18(r)-5(ess )-20(the)18(m)-5(selves)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(more e)20(ffecti)6(v)4(el)6(y th)20(roug)20(h voti)6(ng f)22(o)0(r ce)20(ntral)6( g)20(o)0(vern)20(ment )-20(t)22(han )-20(l)6(o)0(cal)26( )-20(gover)17(nmen)20(t,)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(but they ca)19(nnot e)19(a)-1(si)5(l)5(y)3( expr)16(ess thei)5(r)16( di)5(sconte)19(n)-1(t by l)5(eavi)25(ng.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.058 Tw
+[(These i)6(ssue)20(s)4( are )20(beyond)20( the sco)20(pe of t)22(he cu)20(rrent )20(pape)20(r but rai)6(s)4(e )-20(a numb)20(e)0(r )-20(of)]TJ
+0 -1.16 TD
+0.003 Tc
+0.079 Tw
+[(questi)5(ons. Is)23( l)5(o)-1(cal)5( gove)19(r)-4(nm)16(ent m)16(o)-1(re acc)23(ounta)19(b)-1(l)5(e)-1( and)19( )-20(respo)19(n)-1(si)5(ve )-20(tha)19(n)-1( )-20(cent)21(ral)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(govern)19(m)-4(ent, o)19(r)-4( l)5(e)-1(ss? D)5(o)19( peopl)5(e)19( vote i)5(n)-1( l)25(o)-1(cal)5( body )20(el)5(ecti)5(ons? W)27(ho cont)21(rol)5(s)3( )-20(l)5(o)-1(cal)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.383 Tw
+[(g)-5(o)-5(v)-1(e)-5(r)-8(n)15(m)-8(e)-5(n)-5(t)-3(?)-5( Will lo)-5(ca)-5(l )20(g)-5(o)-5(v)-1(e)-5(r)12(n)-5(m)-8(e)-5(n)-5(t)-3(s)19( b)-5(e)-5(c)-1(o)15(m)-8(e)-5( m)-8(o)15(r)-8(e)-5( )-20(a)-5(cco)15(u)-5(n)-5(t)-3(a)-5(b)-5(l)1(e)15( )-20(a)-5(s)-1( )-20(th)-5(e)-5(y)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(become )20(more)20( pow)6(erf)22(u)0(l)6(?)0( D)6(o)0( t)22(hey re)20(prese)20(n)0(t the i)6(n)20(terests)24( of al)6(l)6( th)20(e )-20(peo)20(pl)6(e )-20(w)6(i)6(t)2(hi)6(n)]TJ
+T*
+0.378 Tw
+[(them? W)8(h)0(a)20(t)2( abo)20(ut the i)6(n)20(terests)24( of pot)22(enti)6(a)0(l)6( mi)26(grants)24(?)0( )-20( )-20(W)8(h)0(i)6(c)4(h )-20(el)6(e)20(m)-3(ent)]TJ
+T*
+0.002 Tc
+0.34 Tw
+[(dom)-5(inates i)24(n)-2( the t)20(ension b)18(e)-2(tween )-20(inc)22(r)-5(easin)18(g )-20(accou)18(n)-2(tability )-20(an)18(d )-20(im)-5(pr)15(oving)]TJ
+0 -1.14 TD
+0.06 Tw
+[(public )20(choice )20(th)18(r)-5(oug)18(h )20(gr)-5(e)18(a)-2(ter)-5( )40(obser)-5(v)22(ability of acti)24(ons, an)18(d gr)-5(e)18(a)-2(ter)-5( )20(hom)-5(o)18(geneity)]TJ
+0 -1.16 TD
+0.219 Tw
+[(on the o)19(ne han)19(d, and)19( decr)16(easing acc)23(ounta)19(b)-1(ility thr)-4(o)19(ugh cap)19(t)1(ur)-4(e by )-20(specific)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(l)6(o)0(cal)6( i)6(n)0(terests)24( on th)20(e othe)20(r?)]TJ
+0 -1.5 TD
+0.002 Tc
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(20)Tj
+1.0952 -0.3095 TD
+1.444 Tw
+[( T)-16(ulloc)-8(k)-8(,)-16( )1428(1980)]TJ
+ET
+endstream endobj 229 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 230 0 obj << /Length 6877 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(43)Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 731.84 Tm
+0.005 Tc
+-0.003 Tw
+[(S)12(o)-4(ver)14(eign)16(ty iss)21(u)-4(es)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 705.92 Tm
+0.003 Tc
+0.079 Tw
+[(P)10(eopl)5(e may b)19(e)-1(l)5(i)5(e)-1(ve that)21( they ca)19(n mak)23(e)-1( bette)19(r deci)5(s)3(i)5(o)19(ns i)5(n)-1( thei)25(r ow)5(n i)5(n)-1(t)21(e)-1(rests.)]TJ
+0 -1.16 TD
+0.139 Tw
+[(In addi)5(ti)5(on,)21( how)5(eve)19(r)-4(, the v)23(a)-1(l)5(ue of )20(devol)5(uti)5(o)19(n )-20(may not )-20(be)19( )-20(si)5(mpl)5(y)3( )-20(m)16(easur)16(ed )-20(i)5(n)]TJ
+T*
+[(terms of)21( the o)19(u)-1(tcomes)23(, obse)19(r)-4(ved as c)23(hanges)23( )-20(i)5(n)-1( )-20(res)23(ource use )-20(an)19(d )-20(al)5(l)5(o)-1(cati)5(on)19(,)]TJ
+T*
+0 Tc
+0.062 Tw
+[(b)-4(u)-4(t)-2( a)-4(l)2(so)-4( th)16(e)-4( p)-4(r)-7(o)-4(c)20(e)-4(ss. T)11(h)-4(e)-4( a)-4(b)-4(ility t)18(o)-4( co)-4(n)-4(t)18(r)-7(o)-4(l yo)-4(u)-4(r)13( )-20(o)-4(w)2(n)-4( )-20(life)-4( )-20(a)16(n)-4(d)-4( )-20(co)16(m)-7(m)-7(u)-4(n)-4(i)2(ty h)-4(a)-4(s)0( )-20(a)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(val)6(ue )20(i)6(rres)24(pecti)6(ve )20(of)22( the us)24(e mad)20(e)0( of i)6(t. )20( Many )20(peopl)6(e w)26(oul)6(d pr)17(efer )20(thei)6(r )20(ow)6(n)]TJ
+0 -1.14 TD
+0.002 Tc
+0 Tw
+[(i)4(neffi)4(ci)4(ency to e)18(ffi)4(ci)4(ency i)4(m)-5(p)18(o)-2(sed by c)22(entr)15(a)-2(l)4( gove)18(r)-5(nme)18(n)-2(t.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.058 Tw
+[(A)11( cri)6(t)2(i)6(c)4(al)6( exampl)6(e )20(of thi)6(s)4( i)6(n)0( N)6(e)0(w)6( Zeal)6(a)20(nd )-20(a)20(r)-3(i)6(s)4(es )-20(w)6(i)6(t)2(h )-20(M)17(aori)6( )-20(sove)20(rei)6(gnty)24(.)2( )-20( )-20(Ma)20(ori)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(do not w)5(a)-1(n)19(t)1( cont)21(rol)5( over)16( thei)5(r l)25(ands an)19(d res)23(ources onl)5(y )-20(beca)19(u)-1(se )-20(th)19(ey )-20(thi)5(n)-1(k )-20(th)19(ey)]TJ
+T*
+0.439 Tw
+[(will get gr)-4(eat)21(er)-4( valu)19(e out )20(of the)19(m)-4(, but )20(also for)16( )-20(r)-4(eas)23(ons )-20(of m)-4(ana and)]TJ
+0 -1.14 TD
+0.239 Tw
+[(rangati)25(r)-4(atang)19(a. T)14(h)-1(i)5(s)3( conce)19(r)-4(n al)5(so )20(appl)5(i)5(e)-1(s to m)16(any s)23(m)-4(al)5(l)5( com)16(m)-4(uni)5(ti)5(es )-20(w)5(h)19(o)]TJ
+0 -1.16 TD
+0.159 Tw
+[(have )20(a )20(str)16(ong l)5(o)-1(c)23(a)-1(l)5( i)5(denti)5(t)1(y o)19(r)-4( a di)5(st)21(rust o)19(f)1( centr)16(a)-1(l)5( auth)19(o)-1(ri)5(ty. )20(Thi)5(s)3( i)5(ssue w)5(a)-1(s)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(epi)6(tomi)6(sed )40(by )20(the )40(bi)6(tter fi)26(ght ove)20(r)-3( the )20(amal)6(gam)17(ati)6(o)0(n)20( of di)6(ffe)20(rent l)26(o)0(cal)6( bodi)6(es)]TJ
+T*
+-0.002 Tw
+[(duri)6(ng th)20(e l)6(o)0(cal)6( g)20(o)0(vern)20(ment )20(refor)17(m)-3(.)]TJ
+/F3 1 Tf
+0 -2.32 TD
+0.007 Tc
+-0.005 Tw
+[(7 C)9(onc)23(l)5(u)-2(si)25(ons)23( an)18(d r)16(ecom)16(m)16(e)3(nd)18(ati)25(ons)]TJ
+/F5 1 Tf
+12 0 2.551 12 127.68 469.52 Tm
+0.003 Tc
+-0.001 Tw
+[(\223God g)19(r)-4(ant )20(me the s)23(e)-1(reni)5(ty)23( to acce)19(pt the t)21(h)-1(i)5(ngs I ca)19(nnot c)23(hange,)]TJ
+0.2466 -1.16 TD
+[(courage )20(to cha)19(nge th)19(e thi)5(ngs I)21( can,)]TJ
+0.2423 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(and the w)6(i)6(s)4(d)20(o)0(m to k)24(now)6( the )20(di)6(ffer)17(ence\224 )20(The S)11(e)20(reni)6(ty P)11(r)-3(ay)24(er, B)11(y)4( R)6(e)0(i)6(nhol)26(d)]TJ
+0.2466 -1.16 TD
+[(N)6(e)0(i)6(buhr)]TJ
+12 0 0 12 99.36 399.92 Tm
+0.138 Tw
+[(The )20(ap)20(prop)20(ri)6(ate )20(l)6(e)0(v)24(e)0(l)6( of dev)24(ol)6(uti)6(on va)20(ri)6(es de)20(pendi)6(n)20(g)0( on th)20(e cha)20(r)-3(acteri)6(sti)6(cs )20(of)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(the i)5(ssue an)19(d the )20(natur)16(e of th)19(e i)5(n)-1(sti)5(t)1(uti)5(o)19(ns i)5(n)-1(vol)5(v)3(ed.)21( W)7(hen d)19(e)-1(vol)5(u)-1(ti)5(on )20(deci)5(s)3(i)5(ons)]TJ
+T*
+0.004 Tc
+0.418 Tw
+[(rel)6(a)0(ti)6(ng to)20( a l)6(a)0(r)17(ge nu)20(mber)17( of i)6(ssues )20(are )20(made )-20(si)26(mul)6(t)2(ane)20(ousl)6(y)4( )-20(tra)20(deoffs)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(i)5(nevi)5(t)1(abl)5(y )20(ari)5(s)3(e)19( )20(amon)19(g )20(i)5(ssues. )20( )40(For)16( )20(a gi)5(ven s)23(e)-1(t of i)5(n)-1(s)23(t)1(i)5(t)1(uti)5(ons a)19(nd j)5(u)-1(ri)5(s)23(d)-1(i)5(c)3(ti)5(onal)]TJ
+T*
+0.12 Tw
+[(bounda)18(r)-5(i)4(es optio)18(ns ar)-5(e)18( m)-5(o)18(r)-5(e)-2( lim)-5(ited s)22(t)0(ill. Never)-5(t)20(heless, by unde)18(r)-5(s)2(tandin)18(g)-2( )-20(the)]TJ
+0 -1.14 TD
+0.239 Tw
+[(nature )20(of the )20(trade)19(offs w)5(e)-1( g)19(a)-1(i)5(n)-1( i)5(n)-1(si)5(ght i)25(n)-1(to the )20(si)5(tuati)5(ons)23( w)5(here )-20(i)25(t)1( )-20(i)5(s)3( )-20(w)5(o)-1(rth)]TJ
+0 -1.16 TD
+0.339 Tw
+[(chal)5(l)5(engi)5(ng t)21(he status)23( quo, )20(the si)5(tua)19(t)1(i)5(ons w)5(her)16(e w)5(e)-1( )-20(sh)19(oul)5(d )-20(en)19(deavou)19(r )-20(to)]TJ
+T*
+0.159 Tw
+[(i)5(m)-4(prove )20(t)21(he )20(func)23(ti)5(oni)5(ng )20(o)19(f)1( )20(exi)5(s)3(ti)5(ng st)21(ructu)19(r)-4(es, an)19(d the si)5(t)21(uati)5(ons w)5(h)19(ere s)23(o)-1(me)]TJ
+T*
+-0.001 Tw
+[(degree )20(of po)19(or deci)5(s)3(i)5(o)19(ns and i)25(neffi)5(ci)5(ency a)19(r)-4(e n)19(o)-1(t w)5(o)-1(rt)21(h add)19(ressi)5(ng.)]TJ
+0 -2.88 TD
+0.18 Tw
+[(T)-7(he )20(RM)-5(A)9( has)22( been )20(used to)18( illustr)-5(a)-2(te)18( how the)18( devoluti)24(on fr)-5(a)18(m)-5(ewo)18(r)-5(k m)-5(a)-2(y b)18(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(appl)6(i)6(ed to )20(a par)17(ti)6(cul)6(a)0(r a)20(r)-3(ea o)20(f)2( pol)6(i)6(cy. I)22(n)0( )-20(many )-20(w)26(a)0(ys, )-20(the 1991 )-20(N)6(e)0(w)6( Zeal)6(a)20(n)0(d)]TJ
+T*
+0.198 Tw
+[(R)6(e)0(source )20(Manag)20(ement)22( A)11(c)4(t i)6(s)4( a bol)6(d )20(pol)6(i)6(cy expe)20(ri)6(ment)22(. It )-20(i)6(s)4( )-20(an)20( )-20(i)6(n)0(teg)20(r)-3(ated,)]TJ
+T*
+0.003 Tc
+0.519 Tw
+[(rel)5(a)-1(ti)5(vel)5(y)3( com)16(p)-1(reh)19(ensi)5(v)3(e pi)5(ec)23(e of r)16(e)-1(sourc)23(e)-1( )-20(man)19(agem)16(ent )-20(l)5(egi)5(sl)5(ati)25(on. )-20( )-20(It)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(emphasi)6(s)4(es l)26(o)0(cal)6( publ)6(i)6(c)4( p)20(a)0(rti)6(c)4(i)6(pati)26(on and)20( has, o)20(n)0( an i)6(n)0(t)22(e)0(rnati)26(onal)6( scal)6(e)0(,)22( )-20(a )-20(very)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(hi)5(gh l)5(e)-1(vel)5( of )20(devol)5(uti)5(o)-1(n)19(.)]TJ
+0 -2.9 TD
+0.059 Tw
+[(Many pr)16(obl)5(ems )20(have a)19(r)-4(i)5(s)3(en si)5(nce)19( the R)5(M)-4(A)10(\222)5(s i)5(n)-1(ce)19(pti)5(on. Many )-20(of)21( )-20(these exi)5(s)3(ted)]TJ
+0 -1.16 TD
+0.004 Tc
+0.438 Tw
+[(under )20(p)20(r)-3(i)6(o)0(r )20(l)26(egi)6(sl)6(ati)6(on, )20(and th)20(e amal)26(gamati)26(on of )20(many A)11(c)4(ts has )20(si)6(mpl)6(y)]TJ
+0 -1.14 TD
+0.118 Tw
+[(concentra)20(ted )20(th)20(em, w)6(h)0(i)6(l)6(e)0( )20(others)24( have )20(ari)6(s)4(en si)6(nc)24(e 199)20(1. Th)20(e pr)17(obl)6(ems )20(have)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(thr)-5(ee b)18(a)-2(sic sour)-5(c)22(e)-2(s:)]TJ
+ET
+endstream endobj 231 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 232 0 obj << /Type /Page /Parent 224 0 R /Resources 234 0 R /Contents 233 0 R >> endobj 233 0 obj << /Length 7399 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(44)Tj
+-34.32 58.98 TD
+0.007 Tc
+[(\(i)9(\))]TJ
+0.9 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.46 0.02 TD
+0.003 Tc
+0.099 Tw
+[(a mi)5(smatch)19( of the)19( j)5(u)-1(ri)5(sdi)5(c)3(ti)5(ons)23( of pol)5(i)5(t)1(i)5(c)3(al)5( )20(deci)5(s)3(i)5(on maki)5(ng, )-20(b)19(enefi)5(t)1(s, )-20(c)23(o)-1(st)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.022 Tw
+[(beari)6(ng, and )-20(i)6(m)17(pl)6(eme)20(n)0(tati)6(on,)]TJ
+-2.36 -2.32 TD
+-0.002 Tc
+[(\()-9(ii\))]TJ
+1.12 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.24 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(poor r)16(e)-1(l)5(a)-1(ti)5(onshi)5(ps)23( amo)19(ng l)5(e)-1(vel)5(s)3( of)21( gove)19(r)-4(nme)19(n)-1(t, and)]TJ
+-2.36 -2.3 TD
+0.001 Tc
+0.001 Tw
+[(\()-6(iii\))-1026(poor)-6( institu)17(t)-1(ional st)19(r)-6(u)-3(ctur)14(es within ju)17(r)-6(i)3(sdictions.)]TJ
+0 -2.9 TD
+0.004 Tc
+0.018 Tw
+[(Thi)6(s)4( pape)20(r has )20(focussed )20(on th)20(e fi)6(rst tw)6(o)20( sources)24( )-20(of )-20(p)20(r)-3(obl)6(ems)24(.)2( )-20( )-20(N)6(e)0(w)6( )-20(Z)15(eal)6(ande)20(rs)]TJ
+0 -1.14 TD
+0.003 Tc
+0.479 Tw
+[(have )20(a te)19(ndency t)21(o)-1( add)19(ress p)19(r)-4(obl)5(ems w)5(i)5(t)21(h l)5(egi)5(sl)5(ati)5(v)3(e )20(and fu)19(ndam)16(ental)]TJ
+0 -1.16 TD
+0.459 Tw
+[(i)5(n)-1(sti)5(t)1(uti)5(onal)5( )20(r)16(e)-1(for)16(m)-4(. )20( )20(W)7(e)-1( concl)25(ude th)19(at the l)25(egal)5(/i)5(nsti)5(tuti)25(onal)5( str)16(u)-1(ctur)16(e of)]TJ
+T*
+0.159 Tw
+[(devol)5(uti)5(on i)5(n)-1( )20(the R)5(M)-4(A)10( i)5(s)3( b)19(a)-1(si)5(cal)5(l)5(y)3( sound.)21( W)7(here)19( devol)5(uti)5(o)19(n i)5(ssues )-20(d)19(o)-1( )-20(ari)5(s)3(e)]TJ
+T*
+0.019 Tw
+[(there )20(i)5(s)3( )20(a )40(trad)19(eoff )20(be)19(tw)5(een )20(t)21(he val)5(ue )20(of com)16(p)-1(reh)19(ensi)5(v)3(e l)5(egi)5(sl)5(ati)25(on and)19( the cos)23(t)1(s)]TJ
+T*
+0.079 Tw
+[(of l)5(egi)5(sl)5(ati)5(on t)21(hat fo)19(rces m)16(any very )20(di)5(ffer)16(ent )-20(i)5(ssues to )-20(be addres)23(sed )-20(w)5(i)5(t)1(hi)5(n )-20(t)21(h)-1(e)]TJ
+0 -1.14 TD
+0 Tw
+[(sam)-5(e)-2( str)15(u)-2(ctur)-5(e)18(.)]TJ
+0 -2.9 TD
+0.099 Tw
+[(The an)19(al)5(ysi)5(s i)5(n)-1( thi)5(s)3( pa)19(per s)23(uggests t)21(hat eff)21(e)-1(cti)5(v)3(e dev)23(ol)5(uti)5(on )20(requi)5(r)16(e)-1(s )-20(atte)19(nti)5(o)-1(n)]TJ
+0 -1.16 TD
+0.039 Tw
+[(to )20(the r)16(e)-1(l)5(a)-1(ti)5(onshi)5(p)19( betw)5(e)-1(e)19(n)-1( cent)21(ral)5( and l)25(o)-1(cal)5( gove)19(r)-4(nm)16(ent as w)5(e)-1(l)5(l)5( as)23( attenti)25(on to)]TJ
+T*
+0.019 Tw
+[(the i)5(deal)5( l)5(o)-1(ca)19(ti)5(on of )20(deci)5(s)3(i)5(on m)16(a)-1(ki)5(ng. The recom)16(m)-4(end)19(ati)5(ons )-20(bel)25(ow)5( )-20(are )-20(l)5(i)5(k)3(el)5(y)23( )-20(to)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(be hel)5(pful)5( i)5(n)19( gui)5(di)5(ng )20(futur)16(e)-1( pol)5(i)5(cy on)19( devol)5(uti)25(on:)]TJ
+0 -1.16 TD
+0 Tc
+0 Tw
+(.)Tj
+12 0 2.551 12 99.36 447.68 Tm
+-0.001 Tc
+0.003 Tw
+[(\()-8(i)1(\))-1468(Cla)-5(r)-8(i)1(fy r)-8(e)-5(sp)-5(o)15(n)-5(sib)-5(ilitie)-5(s)]TJ
+12 0 0 12 99.36 426.8 Tm
+0.004 Tc
+0.018 Tw
+[(P)11(r)-3(obl)6(ems )20(can)20( )20(ari)6(s)4(e )20(w)6(h)20(en cent)22(ral)6( gov)24(ern)20(m)-3(ent i)6(n)0(t)22(ends l)6(o)0(cal)6( )20(gover)17(nment)22( to ma)20(ke)]TJ
+0 -1.14 TD
+0.003 Tc
+0.099 Tw
+[(deci)5(s)3(i)5(ons )20(but )40(does no)19(t make)19( thi)5(s)3( cl)5(ea)19(r. W)7(here)19( i)5(t)1( does)23( w)5(ant to i)25(n)-1(fl)5(uence)19( l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.459 Tw
+[(govern)19(m)-4(ent, )20(i)5(t)1( s)23(houl)5(d p)19(r)-4(ovi)5(de s)23(u)-1(ffi)5(ci)5(ent g)19(u)-1(i)5(dance.)21( Lack of)21( cl)5(ari)5(t)1(y ov)23(er)]TJ
+T*
+0.4 Tw
+[(r)-5(e)-2(sponsibilities le)18(ads to sit)20(uations wh)18(er)-5(e )-20(loc)22(a)-2(l )-20(gove)18(r)-5(nm)-5(e)18(n)-2(t )-20(does not )-20(fe)18(el)]TJ
+T*
+0.004 Tc
+0.298 Tw
+[(empow)6(er)17(ed, )20(an)20(d )20(nei)6(th)20(er )20(l)6(o)0(cal)6( )40(or cen)20(t)2(ral)6( g)20(o)0(vern)20(ment )20(rega)20(rds i)6(t)2(sel)6(f)2( as)24( ful)6(l)6(y)]TJ
+T*
+0.003 Tc
+[(accountabl)5(e)19(.)]TJ
+12 0 2.551 12 102.48 329.84 Tm
+-0.002 Tc
+[(\()-9(ii\))]TJ
+1.1243 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.8757 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(Improve)19( for)16(m)-4(al)5( and i)25(n)-1(for)16(m)-4(al)5( cont)21(racts b)19(e)-1(tw)5(een C)5(e)19(ntral)5( a)19(nd Loc)23(al)]TJ
+0.2466 -1.16 TD
+0.004 Tc
+[(govern)20(m)-3(ent.)]TJ
+12 0 0 12 99.36 288.08 Tm
+0.098 Tw
+[(W)8(here the )20(pol)6(i)6(t)2(i)6(c)4(al)6( deci)6(s)4(i)6(o)20(n-mak)24(e)0(r i)6(s)4( se)20(parat)22(e fro)20(m)-3( the i)26(m)-3(pl)6(em)17(enter)17( of )-20(pol)6(i)6(cy,)]TJ
+0 -1.14 TD
+0.002 Tc
+0.18 Tw
+[(or)-5( )20(the )20(i)24(m)-5(plem)-5(e)18(n)-2(ter)-5( )20(is )20(s)22(epar)15(ate fr)15(om)-5( th)18(e holder)15( of c)22(r)-5(itical skills and )20(objective)]TJ
+0 -1.16 TD
+0.139 Tw
+[(i)5(n)-1(formati)25(on, )20(the)19( effecti)5(v)3(e)19(ness of )20(pol)5(i)5(cy depe)19(nds cri)5(t)1(i)5(c)3(al)5(l)5(y)3( )20(on the )20(qual)5(i)5(t)1(y of)21( the)]TJ
+T*
+-0.001 Tw
+[(\223contrac)23(t)1(\224 be)19(tw)5(een th)19(e tw)5(o. A)10(tte)19(nti)5(on ne)19(eds to be )-20(pai)5(d)19( )-20(to )-20(the)19( )-20(i)5(n)-1(centi)5(v)3(es of )-20(each)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(l)6(e)0(vel)6( of gove)20(r)-3(nme)20(n)0(t to co)20(oper)17(ate w)6(i)6(t)2(h t)22(he othe)20(r an)20(d me)20(et )-20(thei)26(r )-20(needs)24(. )-20( )-20(C)6(ent)22(ral)]TJ
+T*
+0.003 Tc
+0.419 Tw
+[(govern)19(m)-4(ent a)19(genci)5(e)-1(s )20(may nee)19(d to b)19(e)-1( pro)19(a)-1(cti)5(v)3(e i)5(n)-1( p)19(r)-4(ovi)5(d)-1(i)5(ng )-20(s)23(uppo)19(rt )-20(to)]TJ
+0 -1.14 TD
+0.259 Tw
+[(i)5(m)-4(pl)5(ement)21(ers w)5(h)-1(o)19( may n)19(o)-1(t know)5( w)5(h)19(at hel)5(p t)21(hey ne)19(ed an)19(d hence)19( may )-20(b)19(e)]TJ
+0 -1.16 TD
+0.239 Tw
+[(unabl)5(e to c)23(ontr)16(a)-1(ct for i)5(t)21(. One )20(aspect o)19(f)1( the )-20(con)19(t)1(ract)21( )-20(i)5(s)3( )-20(the )-20(fo)19(rmal)5(,)21( )-20(w)5(r)-4(i)5(tten)]TJ
+T*
+0 Tc
+0.402 Tw
+[(sp)-4(e)-4(c)0(ifica)-4(t)-2(io)-4(n)-4( o)-4(f)-2( )20(e)-4(x)0(p)-4(e)-4(c)0(te)16(d)-4( o)-4(u)-4(t)-2(p)16(u)-4(ts, m)-7(o)16(n)-4(i)2(to)-4(r)-7(i)2(n)16(g)-4( r)-7(e)-4(sp)16(o)-4(n)-4(s)0(ib)-4(ilitie)-4(s a)-4(n)16(d)-4( r)-7(e)-4(wa)16(r)-7(d)-4(s.)]TJ
+T*
+0.002 Tc
+0.12 Tw
+[(P)9(e)-2(r)-5(haps an )20(equally, a)18(nd un)18(der)15(-)-5(u)-2(tilised co)18(m)-5(pone)18(nt of co)18(ntr)-5(a)-2(cts)22( is the inf)20(o)-2(r)-5(m)-5(a)-2(l)]TJ
+T*
+0.079 Tw
+[(contract t)21(hat a)19(r)-4(i)5(s)3(es thr)16(ough l)5(o)19(ng te)19(rm )-20(p)19(e)-1(rsonal)5( rel)5(a)-1(ti)5(o)19(n)-1(shi)5(p)-1(s, )-20(co)19(rpor)16(ate )-20(cul)5(t)1(u)19(r)-4(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(and mo)20(ral)6(e)0(, t)22(r)-3(ust an)20(d conce)20(r)-3(n fo)20(r re)20(putati)6(o)0(n)20(.)2( )-20(Th)20(ese )-20(asp)20(e)0(cts )-20(devel)26(op )-20(thr)17(ough)]TJ
+0 -1.16 TD
+0.003 Tc
+0.099 Tw
+[(repeate)19(d)-1( i)5(n)-1(te)19(racti)5(on, i)5(n)19(for)16(m)-4(ati)5(on )-20(sh)19(ari)5(ng,)21( )-20(parti)5(ci)5(p)19(a)-1(ti)5(on )-20(i)5(n)-1( deci)5(s)3(i)5(on-m)16(a)-1(ki)5(ng, and)]TJ
+T*
+0.039 Tw
+[(consi)5(s)3(tent, )20(o)19(pen )20(ho)19(nest )20(b)19(ehavi)5(o)-1(u)19(r)-4( )20(on b)19(o)-1(th si)5(des.)21( S)10(o)-1(me at)21(tenti)5(o)-1(n)19( to pr)16(eservi)5(n)19(g)]TJ
+T*
+-0.001 Tw
+[(and devel)5(o)19(p)-1(i)5(ng th)19(ese asp)19(e)-1(cts of co)19(ntracts )20(may be)19( rew)5(a)19(rdi)5(ng.)]TJ
+ET
+endstream endobj 234 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 235 0 obj << /Type /Page /Parent 224 0 R /Resources 237 0 R /Contents 236 0 R >> endobj 236 0 obj << /Length 7167 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(45)Tj
+12 0 2.551 12 99.36 732.08 Tm
+0.001 Tc
+0.001 Tw
+[(\()-6(iii\))-1026(Reduce duplica)17(t)-1(ion of )20(objective inf)19(o)-3(r)-6(m)14(ation and)17( tech)17(nical skills)]TJ
+12 0 0 12 99.36 711.2 Tm
+0.004 Tc
+0.178 Tw
+[(C)6(entral)6( )20(gov)24(ern)20(m)-3(ent )20(ca)20(n )20(al)6(so con)20(t)2(ri)6(but)22(e to effe)20(cti)6(v)4(e dev)24(ol)6(uti)6(on by)24( retai)26(n)0(i)6(ng a)]TJ
+0 -1.14 TD
+0.003 Tc
+0.459 Tw
+[(rol)5(e)-1( )20(i)5(n)-1( )20(p)19(r)-4(ovi)5(d)-1(i)5(ng )20(e)19(a)-1(sy access t)21(o)-1( techni)5(c)23(a)-1(l)5( i)5(n)-1(form)16(ati)5(on )20(and b)19(e)-1(st-p)19(racti)5(c)3(e)]TJ
+0 -1.16 TD
+0.119 Tw
+[(techni)5(ques. )20( In the)19( case of)21( the R)5(M)-4(A)10(,)1( f)21(o)-1(r exa)19(m)-4(pl)5(e, o)19(ne ap)19(proac)23(h )-20(w)5(oul)5(d )-20(b)19(e)-1( )-20(to)]TJ
+T*
+0.239 Tw
+[(provi)5(de sta)19(ndar)16(di)5(sed \221)5(p)-1(l)5(a)19(ns\222)5( for l)5(o)-1(c)23(a)-1(l)5( counci)5(l)5(s)3( th)19(at can )20(be adj)5(ust)21(ed to l)25(o)-1(cal)]TJ
+T*
+0.139 Tw
+[(needs an)19(d i)5(n)-1(ter)16(e)-1(sts. M)16(a)-1(ke thes)23(e si)5(mpl)5(e)-1( and )-20(cl)5(ose)19( )-20(to )-20(cu)19(rrent practi)5(ce)19( )-20(rath)19(er)]TJ
+T*
+0.001 Tc
+0.141 Tw
+[(than )20(ver)-6(y)1( )40(am)-6(bitio)17(u)-3(s. )20( )20(T)12(h)-3(is )20(will )20(r)-6(educe)17( the cost)19( of cou)17(n)-3(cil com)-6(p)-3(lia)17(nce with th)17(e)]TJ
+0 -1.14 TD
+0.341 Tw
+[(A)8(c)1(t and allow the)17(m)-6( to foc)21(u)-3(s on s)21(pecifically local co)17(ncer)-6(ns. )20( It will allow)]TJ
+0 -1.16 TD
+0.004 Tc
+0.278 Tw
+[(i)6(n)0(cremen)20(tal)6( )20(chan)20(ge )20(and)20( )20(w)6(oul)6(d h)20(e)0(l)6(p)0( mov)24(e)0( the \221)6(s)4(ta)20(tus quo\222)6( )20(from)17( Tow)6(n)0( )20(and)]TJ
+T*
+0.002 Tc
+0.06 Tw
+[(Countr)-5(y)2( P)9(l)4(annin)18(g)-2( A)9(c)2(t type pla)18(nning t)20(o)-2(war)-5(d)-2( RM)-5(A)9( based r)-5(egulati)24(on. )-20( )-20( )-20(It)20( )-20(will )-20(also)]TJ
+T*
+-0.001 Tw
+[(make chan)19(ges an)19(d vari)5(a)19(n)-1(ces i)5(n)-1( p)19(o)-1(l)5(i)5(cy across c)23(ounci)5(l)5(s)3( mo)19(re t)21(r)-4(anspa)19(rent.)]TJ
+12 0 2.551 12 99.36 558.8 Tm
+0 Tc
+0.002 Tw
+[(\()-7(i)2(v\))-967(F)-9(a)-4(cilita)-4(t)-2(e)-4( co)16(m)-7(m)-7(u)-4(n)-4(i)2(c)20(a)-4(tio)-4(n)]TJ
+12 0 0 12 99.36 537.92 Tm
+0.003 Tc
+0.479 Tw
+[(C)5(o)-1(mmuni)5(cati)25(on of ex)23(peri)5(e)19(nces and)19( practi)5(c)23(e)-1(s betw)5(e)19(en cent)21(ral)5( an)19(d )-20(l)5(o)-1(cal)]TJ
+T*
+0.179 Tw
+[(gover)-4(n)19(m)-4(ent )20(a)19(nd )20(am)16(ong local )20(gover)16(nm)-4(en)19(ts will enhanc)23(e lear)16(ning an)19(d r)-4(e)-1(d)19(u)-1(ce)]TJ
+T*
+0.219 Tw
+[(the )20(costs )20(of )40(experi)25(m)-4(entati)25(on. )20(Thi)5(s)3( can )20(be done)19( by foc)23(u)-1(si)5(ng on )20(devel)5(opi)25(ng)]TJ
+T*
+0.339 Tw
+[(rel)5(a)-1(ti)5(onshi)5(ps)23( )20(amon)19(g )20(key p)19(eopl)5(e, a)19(nd by d)19(e)-1(vel)5(opi)5(ng)19( consi)5(s)3(ten)19(t)1( i)5(n)-1(for)16(m)-4(ati)5(o)-1(n)]TJ
+0 -1.14 TD
+0.001 Tc
+[(system)-6(s.)]TJ
+0 -2.9 TD
+0.004 Tc
+0.138 Tw
+[(The cent)22(ral)6( gov)24(ern)20(m)-3(ent )20(may al)6(so h)20(a)0(ve a rol)6(e)0( )-20(i)6(n)0( )-20(i)26(m)-3(provi)6(n)20(g )-20(the )-20(f)22(uncti)6(oni)6(n)20(g)0( )-20(of)]TJ
+0 -1.16 TD
+0.003 Tc
+0.239 Tw
+[(l)5(o)-1(cal)5( i)5(n)-1(sti)5(t)1(uti)5(ons t)21(o)-1( make)19( them)16( mor)16(e)-1( effi)5(ci)5(ent)21( and )20(more)19( )-20(respo)19(n)-1(si)5(ve )-20(to )-20(l)5(o)-1(c)23(a)-1(l)]TJ
+0 -1.14 TD
+[(prefer)16(ences.)]TJ
+12 0 2.551 12 99.36 392.24 Tm
+0 Tw
+[(\()-5(v)2(\))-1185(S)9(tr)-5(engthen)18( the p)18(o)-2(litical accoun)18(tability of loc)22(a)-2(l gove)18(r)-5(nm)-5(e)18(n)-2(t)]TJ
+12 0 0 12 99.36 371.36 Tm
+0.004 Tc
+0.198 Tw
+[(The )20(key )20(a)20(r)-3(gu)20(ment f)22(o)0(r l)6(o)0(cal)6( )20(govern)20(m)-3(ent\222)6(s)4( )20(exi)6(s)4(tence i)6(s)4( t)22(hat l)6(o)0(cal)6( )20(gover)17(nment)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(repres)23(ents l)5(o)-1(cal)5( p)19(r)-4(efe)19(r)-4(ences.)21( A)10(n)-1(y i)5(m)-4(pr)16(ovemen)19(ts i)5(n)-1( th)19(e l)5(o)-1(cal)5( )-20(pol)5(i)5(t)1(i)5(c)3(al)5( process)]TJ
+0 -1.14 TD
+0.04 Tw
+[(will enhance th)18(e bene)18(fits of d)18(e)-2(volution. )20(In som)-5(e)18( )-20(cases )-20(ce)18(ntr)-5(a)-2(l gover)15(nm)-5(ent m)-5(a)-2(y)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.103 Tw
+[(d)-5(e)-5(c)-1(id)-5(e)-5( )20(th)-5(a)-5(t)17( th)-5(e)-5( p)15(o)-5(o)-5(r)-8( p)15(o)-5(litica)-5(l)1( a)-5(cco)-5(u)-5(n)15(ta)-5(b)-5(ility o)-5(f)-3( lo)-5(c)19(a)-5(l g)-5(o)-5(v)-1(e)15(r)-8(n)-5(m)-8(e)15(n)-5(t o)-5(r)-8( )20(th)-5(e)-5(i)1(r)-8( lim)-8(it)17(e)-5(d)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(capaci)5(t)1(y )20(mak)23(e)-1(s )20(i)5(t)1( )20(i)5(napp)19(rop)19(r)-4(i)5(a)-1(te )20(fo)19(r )20(the)19(m)-4( to )20(make ce)19(rtai)5(n typ)19(e)-1(s of d)19(e)-1(ci)5(si)5(on. In)]TJ
+T*
+0.019 Tw
+[(thi)5(s)3( case i)5(t)1( m)16(a)-1(y be a)19(ppro)19(p)-1(ri)5(ate t)21(o)-1( l)5(i)5(m)-4(i)5(t)1( th)19(e scope )20(of )-20(l)5(o)-1(cal)5( )-20(g)19(o)-1(vern)19(ment )-20(ac)23(ti)5(vi)5(ty )-20(as)]TJ
+T*
+0 Tw
+[(a last r)-5(e)-2(so)18(r)-5(t)0(.)]TJ
+12 0 2.551 12 99.36 260.48 Tm
+0.001 Tc
+0.001 Tw
+[(\()-6(v)1(i\))-966(F)-8(a)-3(cilitate In)17(novation)17( in local r)14(egulatio)17(n)]TJ
+12 0 0 12 99.36 239.6 Tm
+[(L)-3(o)-3(c)1(a)-3(l)3( g)-3(o)-3(v)1(e)17(r)-6(n)-3(m)-6(e)17(n)-3(ts m)-6(a)-3(y )20(n)-3(o)-3(t)-1( h)-3(a)-3(v)21(e)-3( th)-3(e)-3( skills a)17(n)-3(d)-3( r)-6(e)-3(s)21(o)-3(u)-3(r)-6(ce)-3(s)21( )-20(to)-3( )-20(in)-3(n)-3(o)17(va)-3(te)-3( )-20(a)17(n)-3(d)-3( )-20(a)-3(d)-3(o)17(p)-3(t)]TJ
+T*
+0.003 Tc
+0.619 Tw
+[(new)5( practi)5(ces)23(.)1( Th)19(ey may )20(not take)19( )-20(i)5(n)-1(to )-20(acc)23(ount )-20(th)19(e )-20(ben)19(efi)5(t)1(s )-20(thei)25(r)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(experi)5(m)-4(e)19(n)-1(tati)5(on c)23(oul)5(d ha)19(ve for)16( othe)19(r di)5(stri)5(cts.)]TJ
+0 -2.9 TD
+0.579 Tw
+[(In )20(some si)5(tu)19(ati)5(ons t)21(he mi)5(sm)16(atches a)19(m)-4(ong)19( l)5(o)-1(cati)5(ons )20(of functi)25(ons and)]TJ
+0 -1.16 TD
+0.159 Tw
+[(characte)19(ri)5(sti)5(cs are)19( so eg)19(regi)5(ous )20(that th)19(e best s)23(o)-1(l)5(u)-1(ti)5(on )20(may be t)21(o)-1( chan)19(ge the)]TJ
+T*
+0.059 Tw
+[(l)5(e)-1(vel)5( )20(of devol)5(u)19(t)1(i)5(on. On)19(e exa)19(m)-4(pl)5(e of t)21(h)-1(i)5(s)3( i)5(s)3( S)10(i)5(gni)5(fi)5(cant N)5(a)-1(t)21(u)-1(ral)5( A)10(r)-4(e)19(a)-1(s di)5(scussed)]TJ
+0 -1.14 TD
+0.004 Tc
+0.038 Tw
+[(i)6(n)0( the com)17(pani)6(on )20(pape)20(r \(W)8(P)11( 98/7)20(a)0(\). C)6(e)20(ntral)6( )-20(g)20(o)0(vern)20(ment )-20(c)24(an )-20(recl)26(ai)6(m )-20(aut)22(hori)6(t)2(y)]TJ
+0 -1.16 TD
+0.003 Tc
+0.199 Tw
+[(over i)5(ssues )20(by usi)5(ng t)21(he pr)16(ovi)5(s)3(i)5(on fo)19(r N)5(a)-1(ti)5(onal)5( P)10(o)-1(l)5(i)5(cy S)10(t)1(ate)19(m)-4(ents )-20(w)5(i)5(t)21(hi)5(n )-20(the)]TJ
+T*
+0.004 Tc
+0.098 Tw
+[(R)6(M)-3(A)11(.)2( Other i)6(s)4(s)24(ues coul)6(d )20(be de)20(al)6(t w)6(i)6(t)2(h w)6(i)6(t)2(hi)6(n t)22(he R)6(M)-3(A)11( but )20(may b)20(enefi)6(t)2( )-20(f)22(r)-3(om)]TJ
+T*
+-0.002 Tw
+[(separate)20( trea)20(tment)22(.)]TJ
+ET
+endstream endobj 237 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 238 0 obj << /Type /Page /Parent 224 0 R /Resources 240 0 R /Contents 239 0 R >> endobj 239 0 obj << /Length 6084 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(46)Tj
+12 0 2.551 12 99.36 725.12 Tm
+0.003 Tc
+-0.001 Tw
+[(F)-6(u)-1(tur)16(e)-1( Directions)23( for Res)23(earch)]TJ
+12 0 0 12 99.36 704.24 Tm
+0.004 Tc
+0.238 Tw
+[(In many w)6(a)0(ys)24( thi)6(s)4( pap)20(er r)17(a)0(i)6(s)4(es as )20(many )-20(qu)20(esti)6(ons )-20(as)24( )-20(i)6(t)2( )-20(answ)6(e)0(rs)24(. )-20( )-20(Fu)20(ture)]TJ
+0 -1.14 TD
+0.003 Tc
+0.359 Tw
+[(researc)23(h)-1( )20(on )20(d)19(e)-1(vol)5(u)-1(ti)5(on )20(c)23(oul)5(d )20(use)19(f)1(ul)5(l)5(y)3( take a)19( num)16(ber o)19(f)1( di)5(recti)5(o)19(ns. It i)5(s)]TJ
+0 -1.16 TD
+0.019 Tw
+[(i)5(nherentl)5(y)3( )40(di)5(ffi)5(cul)5(t)1( to )20(assess the )20(qual)5(i)5(t)1(y of)21( outco)19(mes bec)23(ause pa)19(rt of )20(the poi)25(nt of)]TJ
+T*
+0.519 Tw
+[(devol)5(uti)5(on i)5(s)3( t)21(o)-1( al)5(l)5(o)-1(w)5( het)21(erog)19(eneous outco)19(mes )-20(to refl)5(ect )-20(u)19(nobse)19(r)-4(vabl)5(e)]TJ
+T*
+0.079 Tw
+[(prefer)16(ences. )20( )20(Thus w)5(e)19( can m)16(o)-1(st effec)23(t)1(i)5(v)3(el)5(y expl)5(o)19(r)-4(e the )20(effi)5(ci)5(ency o)19(f)1( devol)5(uti)25(o)-1(n)]TJ
+T*
+[(i)5(n)-1( )20(gener)16(al)5(, )20(and )40(the )20(R)5(M)-4(A)10( )20(i)5(n)-1( p)19(a)-1(rti)5(c)3(ul)5(a)19(r)-4(, by usi)25(ng i)5(ndi)5(r)16(e)-1(ct met)21(hods. A)10( n)19(u)-1(mbe)19(r)-4( of)]TJ
+0 -1.14 TD
+0.004 Tc
+0.338 Tw
+[(empi)6(ri)6(cal)6( a)20(nd the)20(o)0(reti)6(cal)6( i)6(d)20(eas coul)6(d)20( be ex)24(pl)6(ored )20(furth)20(e)0(r. W)8(e)0( l)6(i)6(s)4(t )20(a few)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(questi)5(ons b)19(e)-1(l)5(o)-1(w)5(.)]TJ
+0 -2.9 TD
+0.004 Tc
+(1.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(o)0(w)6( hetero)20(geneo)20(us are)20( N)6(e)0(w)6( Ze)20(al)6(ande)20(rs\222)6( pre)20(f)2(eren)20(ces on )20(di)6(ffere)20(nt i)6(ssues?)]TJ
+-2.36 -2.3 TD
+(2.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(o)0(w)6( w)6(e)0(l)6(l)6( does l)6(o)0(cal)6( g)20(o)0(vern)20(ment )20(refl)6(ect l)6(o)0(c)24(a)0(l)6( pref)22(erenc)24(es?)]TJ
+-2.36 -2.32 TD
+(3.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(C)5(an l)5(o)-1(cal)5( gove)19(r)-4(nme)19(n)-1(t be )20(made )20(mor)16(e)-1( pol)5(i)5(t)1(i)5(c)3(al)5(l)5(y)3( acco)19(untabl)5(e)19(?)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+(4.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+0.019 Tw
+[(W)7(hat )20(compe)19(n)-1(sati)5(on )40(mecha)19(n)-1(i)5(s)3(ms )20(coul)5(d)19( be dev)23(el)5(oped )20(betw)5(een)19( centr)16(a)-1(l)5( and)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(l)6(o)0(cal)6( govern)20(m)-3(ent,)22( and w)6(i)6(t)2(hi)26(n l)6(o)0(cal)6( j)6(u)0(ri)6(s)24(d)0(i)6(c)4(ti)6(ons?)]TJ
+-2.36 -2.32 TD
+(5.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.002 Tc
+0.08 Tw
+[(What )20(ar)-5(e )20(t)20(he )20(cap)18(ability )20(lim)-5(itations)22( of local g)18(o)-2(ver)-5(n)18(m)-5(ent)20(? S)9(hould we )20(tr)-5(y to)]TJ
+0 -1.16 TD
+0 Tc
+0.002 Tw
+[(im)-7(p)-4(r)-7(o)-4(v)0(e)-4( t)18(h)-4(e)-4(i)2(r)-7( ca)16(p)-4(a)-4(b)-4(ility, lim)-7(it t)18(h)-4(e)-4(i)2(r)-7( a)-4(c)0(tiviti)22(e)-4(s)0(, o)-4(r)-7( )20(a)-4(cce)-4(p)-4(t)-2( t)18(h)-4(e)-4( in)-4(e)-4(fficie)16(n)-4(cy?)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+(6.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(hat i)5(n)-1(centi)5(v)3(es d)19(o)-1( cent)21(ral)5( gove)19(r)-4(nm)16(ent ag)19(enci)5(e)-1(s hav)23(e )-20(to )-20(p)19(r)-4(ovi)5(de proacti)5(v)23(e)]TJ
+0 -1.16 TD
+[(and reac)23(ti)5(ve assi)5(stanc)23(e to l)5(o)-1(cal)5( )20(gover)16(nmen)19(t?)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+(7.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(o)0(w)6( approp)20(ri)6(ate i)6(s)4( t)22(he spl)6(i)6(t, i)6(n)20( the cu)20(rren)20(t)2( R)6(M)-3(A)11(,)2( )-20(betw)6(e)20(en )-20(re)20(gi)6(onal)6( )-20(co)20(unci)6(l)6(s)]TJ
+0 -1.14 TD
+[(and ter)17(r)-3(i)6(t)2(ori)6(a)0(l)6( l)26(o)0(cal)6( auth)20(o)0(ri)6(ti)6(es?)]TJ
+-2.36 -2.32 TD
+0.138 Tw
+[(Fi)6(nal)6(l)6(y)4( )20(w)6(e)0( )20(em)17(phasi)6(s)4(e )20(t)22(hat eff)22(e)0(cti)6(v)4(e pol)6(i)6(cy )20(maki)6(ng a)20(nd i)6(m)-3(pl)26(ement)22(ati)6(on r)17(equi)6(r)17(e)]TJ
+0 -1.16 TD
+0.003 Tc
+0.039 Tw
+[(more t)21(han co)19(rrect l)5(e)-1(v)23(e)-1(l)5(s)3( of d)19(e)-1(vol)5(u)-1(ti)5(on. )20( Many a)19(s)3(pects o)19(f)1( the R)25(M)-4(A)10( w)5(e)-1(re bey)23(ond)]TJ
+T*
+[(the )20(scope )40(of )20(thi)5(s)3( )20(pa)19(per. )20( Othe)19(r)-4( key i)5(ssues f)21(o)-1(r a)19(n)-1(y revi)5(ew)5( )20(of the )20(effecti)5(v)3(en)19(ess of)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(the R)5(M)-4(A)10( i)5(n)-1(cl)5(ude cl)5(a)19(r)-4(i)5(t)1(y an)19(d consi)5(s)3(tenc)23(y of th)19(e l)5(a)-1(w)5( i)5(t)1(sel)5(f, tec)23(hni)5(cal)5( i)5(ssues )20(of )-20(how)]TJ
+0 -1.16 TD
+0.179 Tw
+[(to i)5(n)-1(tegr)16(ate di)5(ff)21(erent )20(envi)5(r)-4(o)19(n)-1(ment)21(al)5( conce)19(r)-4(ns, an)19(d the potenti)5(a)-1(l)5( of )-20(al)5(te)19(rnati)5(v)3(e)]TJ
+T*
+0.139 Tw
+[(pol)5(i)5(cy i)5(n)-1(strum)16(ents fo)19(r achi)5(evi)5(n)19(g the )20(goal)5(s of )20(the A)10(c)3(t. A)10(l)5(l)5( of )-20(th)19(ese )-20(i)5(ssues are)]TJ
+T*
+-0.001 Tc
+0.083 Tw
+[(im)-8(p)-5(o)-5(r)-8(ta)15(n)-5(t. By cla)-5(r)-8(ifyin)-5(g)15( th)-5(e)-5( issu)15(e)-5(s)-1( r)-8(e)-5(la)-5(t)17(e)-5(d)-5( to)-5( )20(d)-5(e)-5(v)-1(o)-5(l)1(u)-5(t)-3(io)-5(n)15( we)-5( h)-5(o)-5(p)15(e)-5( th)-5(a)-5(t)-3( it)17( will )-20(b)-5(e)]TJ
+T*
+0.004 Tc
+0.218 Tw
+[(easi)6(e)0(r )20(to )40(di)6(sti)6(ngui)6(sh )40(probl)6(e)20(m)-3(s that)22( ari)6(s)4(e f)22(r)-3(om d)20(e)0(vol)6(u)0(ti)6(o)20(n)0(, and)20( pro)20(b)0(l)6(e)0(ms th)20(at)]TJ
+0 -1.14 TD
+0.002 Tc
+0.06 Tw
+[(would )20(ar)-5(ise )20(in)18( any str)15(u)-2(ctur)15(e. A)9(nalysts will be m)15(o)-2(r)-5(e)-2( )20(able to)18( unde)18(r)-5(s)2(tand)18( the t)20(r)-5(ue)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(causes of p)19(r)-4(obl)5(e)19(m)-4(s, anal)5(ys)23(e them)16( i)5(n)-1( the )20(appro)19(p)-1(ri)5(at)21(e context)21(.)]TJ
+ET
+endstream endobj 240 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 241 0 obj << /Length 6224 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(47)Tj
+/F3 1 Tf
+-34.32 57.54 TD
+-0.004 Tc
+[(APPENDIC)-22(E)3(S)]TJ
+0 -2.44 TD
+0.006 Tc
+-0.004 Tw
+[(A)8(ppen)17(d)-3(i)4(x)2( O)24(n)-3(e:)19( Th)17(e R)8(e)2(s)22(our)15(ce M)19(a)2(na)22(gem)15(e)2(n)17(t)-1( A)8(c)2(t 1)22(991)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 673.165 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 673.52 Tm
+0.004 Tc
+0.458 Tw
+[(The R)6(e)0(sou)20(r)-3(ce )20(Manag)20(ement)22( A)11(c)4(t 1991 \(R)6(MA)11(\) )-20(i)6(s)4( )-20(th)20(e )-20(pri)6(n)0(ci)6(p)20(a)0(l)6( )-20(l)6(egi)6(sl)6(ati)6(o)0(n)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(governi)5(ng)19( )20(the us)23(e of N)5(e)-1(w)5( )20(Zeal)5(an)19(d\222)5(s l)5(and, )20(ai)5(r, w)5(a)-1(te)19(r, ecosys)23(tems, s)23(o)-1(i)5(l)5(s)3(, geol)5(ogy)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(and the )20(bui)6(l)6(t)2( envi)6(r)17(onme)20(n)0(t. A)11(l)6(so cont)22(rol)6(l)6(ed a)20(r)-3(e n)20(o)0(i)6(s)4(e, pol)6(l)6(u)0(ti)6(o)20(n)0( )-20(and)20( )-20(geoth)20(e)0(rm)17(al)]TJ
+0 -1.14 TD
+0.001 Tc
+(activities.)Tj
+10.08 0 0 10.08 99.36 617.725 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 604.16 Tm
+0.004 Tc
+0.158 Tw
+[(The R)6(M)-3(A)11( w)6(a)0(s i)6(n)0(t)22(ended)20( to p)20(r)-3(ovi)6(de a )20(fram)17(ew)6(ork f)22(o)0(r )-20(si)6(mpl)6(i)6(f)2(yi)6(n)20(g)0( )-20(envi)6(r)17(onme)20(n)0(tal)]TJ
+0 -1.16 TD
+0.258 Tw
+[(manage)20(ment i)6(n)20( N)6(e)0(w)6( Ze)20(al)6(and. I)22(n)0( total)6( i)6(t)22( repea)20(l)6(ed 5)20(9)0( statut)22(es. )-20(T)15(he )-20(most)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(si)5(gni)5(fi)5(cant of t)21(he re)19(peal)5(ed )20(acts w)5(e)-1(r)16(e)-1(:)]TJ
+10.08 0 0 10.08 99.36 562.285 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 547.76 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(The W)8(a)0(te)20(r and S)11(o)0(i)6(l)6( C)6(o)20(nservati)26(on A)11(c)4(t \(19)20(67\);)]TJ
+10.08 0 0 10.08 99.36 533.485 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 519.2 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(The C)6(l)6(ean A)11(i)6(r)17( A)11(c)4(t \(197)20(2\);)]TJ
+10.08 0 0 10.08 99.36 504.925 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 490.4 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(The T)15(o)0(w)6(n)0( and)20( C)6(ount)22(ry P)11(l)6(anni)6(ng A)11(c)4(t \()17(1977)20(\); and)]TJ
+10.08 0 0 10.08 99.36 476.365 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 461.84 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(The N)6(o)0(i)6(s)4(e C)6(o)20(ntrol)6( A)11(c)4(t \()17(1982)20(\).)]TJ
+10.08 0 0 10.08 99.36 447.565 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3571 TD
+( )Tj
+12 0 0 12 99.36 434.24 Tm
+0.004 Tc
+0.138 Tw
+[(U)6(nder p)20(r)-3(evi)6(ous A)11(c)4(ts dev)24(oted t)22(o)0( reso)20(urce )20(manag)20(emen)20(t i)6(n)0( N)6(e)0(w)6( Z)15(eal)6(and ther)17(e)]TJ
+0 -1.16 TD
+0.003 Tc
+0.179 Tw
+[(w)5(a)-1(s )20(w)5(i)5(desprea)19(d )20(di)5(ssati)5(sfacti)25(on. )20( In )20(many c)23(a)-1(ses, the)19( l)5(egi)5(sl)5(ati)5(on w)25(a)-1(s seen )20(as)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(confl)6(i)6(c)4(ti)6(ng, ove)20(r)-3(l)6(appi)6(n)20(g)0( and c)24(onfusi)6(ng.)22( Maj)6(o)20(r pr)17(obl)6(ems i)6(d)20(enti)6(f)2(i)6(ed )20(at the )20(ti)6(me)]TJ
+T*
+0.003 Tc
+[(i)5(n)-1(cl)5(uded:)]TJ
+10.08 0 0 10.08 99.36 378.205 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 363.92 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(the col)5(l)5(e)-1(cti)5(on )20(of A)10(c)3(ts di)5(d no)19(t have )20(a stand)19(ard )-20(p)19(u)-1(rpos)23(e )-20(as )-20(th)19(ey )-20(w)5(e)-1(re )-20(w)25(r)-4(i)5(tten)]TJ
+0 -1.16 TD
+[(for a va)19(ri)5(ety of )20(purp)19(o)-1(ses;)]TJ
+10.08 0 0 10.08 99.36 335.725 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 321.44 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+0.078 Tw
+[(there w)6(e)20(re a n)20(u)0(mbe)20(r)-3( of a)20(genci)6(e)0(s i)6(n)0(v)24(o)0(l)6(v)4(ed i)6(n)0( )20(resou)20(r)-3(ce )-20(ma)20(nage)20(ment, )-20(w)6(i)6(t)2(h)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(over)-5(lappin)18(g)-2( r)-5(e)-2(sp)18(onsibilities an)18(d poo)18(r)-5( accou)18(n)-2(tability;)]TJ
+10.08 0 0 10.08 99.36 293.245 Tm
+0 Tc
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 278.96 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(consent p)19(r)-4(ocedu)19(res w)5(e)19(re l)5(engt)21(hy and )20(compl)5(e)-1(x;)]TJ
+10.08 0 0 10.08 99.36 264.685 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 250.16 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(enforce)20(ment a)20(nd m)17(oni)6(tori)6(n)20(g)0( w)6(e)0(re w)26(eak; an)20(d)]TJ
+10.08 0 0 10.08 99.36 235.885 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 221.6 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(the oppo)20(rtuni)6(ty )20(for th)20(e publ)6(i)6(c)4( t)22(o)0( be i)6(n)0(v)24(o)0(l)6(v)4(ed w)6(a)0(s l)6(i)6(m)-3(i)6(t)22(ed.)]TJ
+10.08 0 0 10.08 99.36 207.325 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 193.76 Tm
+0.004 Tc
+0.258 Tw
+[(A)11( more i)6(n)0(te)20(grate)20(d)0( and )-20(c)24(oordi)26(nated process for resou)20(r)-3(ce )-20(ma)20(nage)20(ment )-20(w)6(a)0(s)]TJ
+0 -1.14 TD
+0.005 Tc
+[(requi)7(re)21(d.)]TJ
+10.08 0 0 10.08 99.36 165.805 Tm
+0 Tc
+0 Tw
+( )Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 152 Tm
+0.006 Tc
+-0.004 Tw
+[(Major)15( A)8(s)2(p)17(ects )20(of )20(the R)28(M)-1(A)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 125.485 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 125.84 Tm
+0.003 Tc
+0.059 Tw
+[(The )20(R)5(M)-4(A)10( i)5(s)3( bas)23(ed on )20(tw)5(o maj)5(o)19(r assu)19(mpti)5(ons: )20(that g)19(o)-1(verni)5(n)19(g bodi)25(es cl)5(osest to)]TJ
+T*
+0.099 Tw
+[(resourc)23(e)-1(s )20(are)19( )20(the )20(m)16(o)-1(st ap)19(prop)19(ri)5(ate to)19( gove)19(r)-4(n the )20(use of t)21(hose )20(resou)19(r)-4(ces, an)19(d)]TJ
+0 -1.16 TD
+0.419 Tw
+[(that i)5(t)1( i)5(s)3( mo)19(re effi)5(ci)5(e)19(n)-1(t to f)21(o)-1(cus cont)21(rol)5( )-20(an)19(d )-20(regu)19(l)5(a)-1(ti)5(on on )-20(the advers)23(e)]TJ
+ET
+endstream endobj 242 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 243 0 obj << /Length 7157 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(48)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.159 Tw
+[(envi)5(r)-4(onm)16(ental)5( ef)21(fects of s)23(o)-1(me ac)23(ti)5(vi)5(ti)5(es rat)21(her t)21(han th)19(e acti)5(vi)5(ti)5(es )-20(th)19(emsel)5(v)3(es.)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(There)20(f)2(ore, autho)20(ri)6(ty )-20(fo)20(r )-20(i)6(m)-3(pl)6(e)20(m)-3(enti)6(ng the )-40(R)6(M)-3(A)11( )-40(i)6(s)4( )-40(d)20(e)0(vol)6(v)4(ed )-40(to)20( )-40(l)6(o)0(cal)6( )-40(an)20(d )-40(regi)6(o)20(nal)]TJ
+T*
+0.003 Tc
+[(authori)5(t)1(i)5(e)-1(s.)]TJ
+10.08 0 0 10.08 99.36 703.885 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 690.32 Tm
+0.001 Tc
+0.001 Tw
+[(Ro)-8(le o)12(f)-6( Cen)12(t)-6(r)10(a)-3(l Go)-8(v)17(e)-3(r)10(n)-8(m)10(e)-3(n)-8(t)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 663.805 Tm
+0 Tc
+0 Tw
+( )Tj
+12 0 0 12 99.36 664.16 Tm
+0.003 Tc
+0.439 Tw
+[(C)5(entral)5( gov)23(ern)19(m)-4(ent h)19(a)-1(s a r)16(o)-1(l)5(e)-1( i)5(n)-1( )-20(setti)5(n)19(g)-1( )-20(pol)5(i)5(cy )-20(on)19( )-20(matt)21(ers )-20(of nati)5(onal)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(si)6(gni)6(fi)6(cance an)20(d moni)6(t)22(o)0(ri)6(ng )20(the i)6(m)-3(pl)26(ement)22(ati)6(on of)22( the A)11(c)4(t. )-20( )-20(C)6(e)20(ntral)6( )-20(g)20(o)0(vern)20(ment)]TJ
+0 -1.14 TD
+0.003 Tc
+0.679 Tw
+[(may i)5(ssue n)19(a)-1(ti)5(onal)5( p)19(o)-1(l)5(i)5(cy statem)16(ents, p)19(r)-4(epa)19(re )-20(nati)25(onal)5( )-20(envi)25(r)-4(onm)16(ental)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(standards)24(, or c)24(a)0(l)6(l)6(-)-3(i)6(n)0( any )20(resou)20(r)-3(ce )-20(cons)24(ent )-20(a)20(ppl)6(i)6(c)4(ati)6(on )-20(f)22(o)0(r )-20(a Mi)6(ni)6(steri)6(a)0(l)6( deci)6(s)4(i)6(on.)]TJ
+T*
+0.003 Tc
+0.179 Tw
+[(A)10(t)1( thi)5(s)3( ti)5(me, how)5(ev)23(er, o)19(n)-1(l)5(y)3( one )20(nati)5(onal)5( )20(pol)5(i)5(cy state)19(m)-4(ent, )20(the C)5(oast)21(a)-1(l)5( P)10(o)-1(l)5(i)5(c)3(y)]TJ
+T*
+-0.001 Tw
+[(S)10(t)1(atement, )20(has bee)19(n w)5(r)-4(i)5(tte)19(n.)]TJ
+10.08 0 0 10.08 99.36 580.525 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.3571 TD
+( )Tj
+12 0 0 12 99.36 567.2 Tm
+0.003 Tc
+0.179 Tw
+[(The Mi)5(ni)5(st)21(ry fo)19(r the E)10(n)-1(vi)5(r)16(onme)19(n)-1(t mak)23(e)-1(s submi)5(ssi)5(o)19(n)-1(s on d)19(r)-4(aft )20(regi)5(on)19(al)5( pl)5(ans)]TJ
+0 -1.16 TD
+0.119 Tw
+[(and )20(provi)25(des )20(sup)19(port )20(a)19(nd )20(tr)16(ai)5(ni)5(ng vi)5(a t)21(he p)19(r)-4(ovi)5(s)3(i)5(on of)21( best p)19(r)-4(acti)5(ce g)19(u)-1(i)5(del)5(i)5(nes)]TJ
+T*
+-0.001 Tw
+[(and the )20(provi)5(s)3(i)5(on )20(of i)5(n)-1(fo)19(rmati)5(o)19(n)-1( docu)19(m)-4(ents.)]TJ
+10.08 0 0 10.08 99.36 525.085 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 511.52 Tm
+0.002 Tc
+[(Ro)-7(les o)13(f)-5( L)13(o)-7(cal A)24(u)-7(t)15(h)-7(o)-7(r)11(itie)18(s)]TJ
+/F5 1 Tf
+10.08 0 0 10.08 99.36 485.005 Tm
+0 Tc
+( )Tj
+12 0 0 12 99.36 485.36 Tm
+0.003 Tc
+-0.001 Tw
+[(R)5(egi)5(onal)5( counci)5(l)5(s)3( )20(mana)19(ge w)5(a)-1(te)19(r, soi)5(l)5(,)1( ge)19(othe)19(rmal)5( r)16(e)-1(sourc)23(e)-1(s, pol)5(l)5(u)-1(ti)5(o)19(n)-1(, and)19( )-20(l)5(and)]TJ
+0 -1.16 TD
+0.059 Tw
+[(use )20(that a)19(ffects na)19(tural)5( )20(resou)19(r)-4(ces. R)5(e)19(gi)5(ons pre)19(par)16(e re)19(gi)5(onal)5( pol)5(i)5(cy st)21(atem)16(ents)]TJ
+T*
+0.199 Tw
+[(and coastal)5( )20(pl)5(ans w)5(h)-1(i)5(c)3(h )20(must b)19(e)-1( consi)5(s)3(te)19(nt )-20(w)5(i)5(t)1(h )-20(nati)25(onal)5( )-20(pol)5(i)5(cy )-20(st)21(ateme)19(n)-1(ts.)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(R)6(egi)6(onal)6( )20(counci)6(l)6(s)4( )40(are )40(responsi)26(b)0(l)6(e)0( for )20(moni)6(to)20(ri)6(ng t)22(he state)20( of the)20( envi)6(r)-3(o)20(n)0(men)20(t)2(,)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(consent co)19(mpl)5(i)5(ance )20(and pl)5(a)19(n)-1( effecti)5(v)3(e)19(ness.)]TJ
+10.08 0 0 10.08 99.36 415.645 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 402.08 Tm
+0.004 Tc
+0.198 Tw
+[(Terri)6(t)22(o)0(ri)6(al)6( l)6(o)0(cal)6( )20(autho)20(ri)6(ti)6(es ar)17(e resp)20(onsi)6(b)0(l)6(e)0( f)22(o)0(r l)6(and)20( )-20(man)20(agem)17(ent, )-20(sub)20(d)0(i)6(v)4(i)6(s)4(i)6(o)0(n)]TJ
+0 -1.16 TD
+0.098 Tw
+[(and noi)6(se c)24(ontrol)6(.)22( They)24( are )20(requi)26(red t)22(o)0( )-20(devel)6(o)20(p)0( )-20(di)6(stri)6(ct pl)6(ans, )-20(w)6(h)0(i)6(c)4(h must )-20(b)20(e)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(consi)5(s)3(tent w)5(i)5(t)1(h )20(rel)5(e)-1(vant)21( regi)5(o)19(nal)5( and)19( nati)5(o)-1(n)19(a)-1(l)5( pl)5(ans.)]TJ
+10.08 0 0 10.08 99.36 360.205 Tm
+0 Tc
+0 Tw
+( )Tj
+0 -1.381 TD
+( )Tj
+12 0 0 12 99.36 346.64 Tm
+0.004 Tc
+0.218 Tw
+[(A)11(l)6(l)6( l)6(o)0(cal)6( authori)6(t)2(i)6(e)0(s )20(are )20(requi)6(r)17(ed un)20(der sec)24(t)2(i)6(on 6 o)20(f)2( the R)26(M)-3(A)11( )-20(to )-20(pr)17(ovi)6(de )-20(fo)20(r)]TJ
+0 -1.16 TD
+0.003 Tc
+0.379 Tw
+[(matters )20(of nati)5(o)19(nal)5( i)5(m)-4(p)19(o)-1(rtanc)23(e. T)14(hese a)19(r)-4(e defi)25(ned as the )-20(p)19(r)-4(otecti)5(o)19(n)-1( )-20(or)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(preserv)24(a)0(ti)6(on of:)]TJ
+10.08 0 0 10.08 99.36 304.525 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 290.24 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+0.239 Tw
+[(the natu)19(r)-4(al)5( cha)19(r)-4(acte)19(r of th)19(e coastal)5( )20(envi)5(r)-4(on)19(ment \(i)5(ncl)5(udi)5(n)19(g)-1( )-20(the )-20(co)19(astal)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(mari)6(ne )20(area)20(\), w)6(e)0(tl)6(an)20(ds, and)20( l)6(a)0(kes an)20(d ri)6(vers)24(;)]TJ
+10.08 0 0 10.08 99.36 262.045 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 247.76 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+0.819 Tw
+[(outstandi)5(n)19(g)-1( natu)19(r)-4(al)5( fea)19(t)1(ures and )-20(l)5(a)-1(n)19(d)-1(scapes )-20(fr)16(om )-20(i)25(napp)19(ropri)5(a)19(te)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(subdi)5(vi)5(si)5(on, use,)21( and d)19(e)-1(vel)5(o)-1(p)19(m)-4(ent;)]TJ
+10.08 0 0 10.08 99.36 219.565 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 205.28 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+0.399 Tw
+[(areas )20(of )20(si)25(gni)5(fi)5(cant i)5(n)19(di)5(geno)19(us veget)21(ati)5(on a)19(nd si)5(gni)5(fi)5(can)19(t)1( habi)5(ta)19(ts of)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(i)6(ndi)6(genous f)22(auna;)]TJ
+10.08 0 0 10.08 99.36 177.085 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 162.8 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(publ)5(i)5(c)3( access to )20(and al)5(o)19(ng th)19(e coastal)5( )20(mari)5(n)19(e)-1( are)19(a)-1(, l)5(a)-1(kes, )20(and ri)5(v)23(e)-1(rs; a)19(n)-1(d)]TJ
+10.08 0 0 10.08 99.36 148.525 Tm
+0 Tc
+0 Tw
+( )Tj
+/F12 1 Tf
+12 0 0 12 99.36 134 Tm
+(\267)Tj
+/F5 1 Tf
+0.46 -0.02 TD
+( )Tj
+1.9 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(the rel)6(a)0(ti)6(o)20(n)0(shi)6(p)0( of)22( Mao)20(r)-3(i)6( and t)22(hei)6(r cul)6(t)22(ure )20(and tr)17(adi)6(ti)6(ons )-20(w)6(i)6(t)2(h)20( )-20(thei)6(r ancestr)17(al)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(l)5(ands, w)5(a)-1(ter)16(,)1( si)5(tes, w)5(a)-1(a)19(h)-1(i)5( tapu,)21( and o)19(t)1(her )20(taong)19(a.)]TJ
+ET
+endstream endobj 244 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F12 168 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 245 0 obj << /Length 7355 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(49)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.019 Tw
+[(Local)5( )20(gove)19(r)-4(nme)19(n)-1(t )20(age)19(nci)5(e)-1(s )20(ar)16(e req)19(u)-1(i)5(r)-4(ed )20(under)16( S)10(e)-1(cti)5(on 32)19( of th)19(e R)5(M)-4(A)10( to sati)5(sfy)]TJ
+0 -1.16 TD
+0.239 Tw
+[(themsel)5(v)3(es )20(t)21(hat any)23( pol)5(i)5(cy pr)16(oposed)19( to achi)5(eve)19( the )20(purp)19(o)-1(ses of t)21(he A)10(c)3(t i)5(s)]TJ
+T*
+0.219 Tw
+[(necessary a)19(nd i)5(s)3( sup)19(e)-1(ri)5(or)16( )-20(to )-20(any pol)5(i)5(cy )-20(al)5(te)19(rnati)5(v)3(es. )-20(They have )-20(si)5(g)19(n)-1(i)5(f)1(i)5(c)3(ant)]TJ
+T*
+0.001 Tc
+0.301 Tw
+[(flexibility )20(to )20(choose)17( )20(any p)17(o)-3(licy m)-6(e)-3(cha)17(n)-3(ism)-6( they)21( conside)17(r)-6( m)-6(o)-3(st)19( app)17(r)-6(opr)-6(iat)19(e)-3(.)]TJ
+0 -1.14 TD
+0.003 Tc
+0.059 Tw
+[(They m)16(a)-1(y use )20(rul)5(e)-1(s, m)16(a)-1(rket )20(mecha)19(n)-1(i)5(s)3(ms or)16( educati)25(on pr)16(ogra)19(mmes )20(as )-20(l)5(ong as)]TJ
+0 -1.16 TD
+0.079 Tw
+[(they avoi)5(d a)19(nd mi)5(ti)5(g)19(a)-1(te eff)21(e)-1(cts on t)21(he )-20(envi)25(r)-4(onm)16(ent. )-20( )-20(O)21(n)-1( )-20(pri)5(v)3(at)21(e )-20(l)5(and, acti)5(vi)5(ti)5(es)]TJ
+T*
+0.004 Tc
+0.038 Tw
+[(are al)6(l)6(o)0(w)6(ed )20(unl)6(ess sp)20(eci)6(f)2(i)6(c)4(al)6(l)6(y)4( pro)20(h)0(i)6(b)0(i)6(t)2(ed i)6(n)0( )20(a pl)6(an or )-20(r)17(u)0(l)6(e)0(. )-20( )-20(F)15(o)0(r )-20(al)6(l)6( )-20(ot)22(her natur)17(al)]TJ
+T*
+0.003 Tc
+0.259 Tw
+[(resourc)23(e)-1(s, acti)5(vi)5(ti)5(es a)19(r)-4(e p)19(r)-4(ohi)5(bi)5(te)19(d and )20(requi)25(re a co)19(nsent, )20(unl)5(ess )-20(exp)19(r)-4(essl)5(y)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(al)6(l)6(o)0(w)6(ed i)6(n)0( a pl)6(a)20(n)0(.)]TJ
+0 -2.34 TD
+0.003 Tc
+0.039 Tw
+[(There)19( are fi)5(v)23(e)-1( types )20(of res)23(ource c)23(onsents,)21( l)5(and us)23(e, subdi)5(vi)5(si)5(on)19(, coastal)5(,)21( )-20(w)5(a)-1(ter)]TJ
+0 -1.16 TD
+0.139 Tw
+[(and di)5(scha)19(r)-4(ge. A)10(c)3(ti)5(vi)5(ti)5(es a)19(r)-4(e al)5(so cl)25(assi)5(fi)5(ed )-20(i)5(n)-1(to)19( )-20(fi)5(ve )-20(cate)19(gori)5(e)-1(s rangi)5(n)19(g)-1( )-20(fro)19(m)]TJ
+0 -1.14 TD
+0.004 Tc
+0.178 Tw
+[(permi)6(tte)20(d )20(acti)6(vi)6(ti)6(es )40(\(w)6(here)20( )20(no cons)24(ent i)6(s)4( r)17(equi)6(re)20(d\) to)20( pro)20(h)0(i)6(b)0(i)6(t)2(ed acti)6(vi)6(ti)6(es)24( \(an)]TJ
+0 -1.16 TD
+0.003 Tc
+0.379 Tw
+[(acti)5(vi)5(ty i)5(s)3( expressl)5(y )20(prohi)5(bi)5(t)21(ed\). The thre)19(e )-20(i)5(n)-1(ter)16(m)-4(edi)5(at)21(e )-20(categ)19(o)-1(ri)5(es )-20(al)5(l)5(o)-1(w)]TJ
+T*
+0.299 Tw
+[(acti)5(vi)5(ti)5(es )20(but )20(w)5(i)5(t)1(h co)19(ndi)5(ti)5(ons. )20( R)5(egi)5(ons i)5(ssu)19(e coastal)5(,)21( w)5(a)-1(ter )20(and di)5(sch)19(arge)]TJ
+T*
+-0.001 Tw
+[(permi)5(ts. )20(TLA)10(s)3( i)5(ssue l)5(a)19(nd use )20(and su)19(bdi)5(vi)5(si)5(on cons)23(ents.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 509.6 Tm
+[(P)10(u)-6(b)-6(lic P)10(a)-1(r)12(t)-4(ici)21(p)-6(ati)21(o)-6(n)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 483.44 Tm
+0.139 Tw
+[(The )20(pu)19(bl)5(i)5(c)3( )20(can )20(m)16(a)-1(ke )20(sub)19(m)-4(i)5(ssi)5(ons on )20(both t)21(he res)23(ource)19( consent)21( proc)23(ess and)]TJ
+T*
+0.159 Tw
+[(the pl)5(anni)5(n)19(g)-1( pr)16(ocesses fo)19(r pl)5(ans )20(and r)16(egi)5(onal)5( p)19(o)-1(l)5(i)5(cy state)19(m)-4(ents. )20( )-20(The)19( )-20(publ)5(i)5(c)]TJ
+T*
+0.004 Tc
+0.198 Tw
+[(can )20(al)6(so )20(seek )40(a decl)6(a)20(rati)6(on f)22(r)-3(om )20(the E)11(n)0(vi)6(ro)20(nment)22( C)6(ourt )20(on pl)6(an)20( provi)6(s)4(i)6(o)20(ns.)]TJ
+0 -1.14 TD
+0.758 Tw
+[(The )20(E)11(n)0(vi)6(ron)20(m)-3(ent )20(C)26(ourt )20(c)24(an i)6(m)-3(p)20(o)0(se enf)22(orceme)20(nt o)20(r)-3(ders)24( to res)24(t)2(rai)6(n)]TJ
+0 -1.16 TD
+0.003 Tc
+0.239 Tw
+[(envi)5(r)-4(onm)16(ental)5(l)5(y)3( da)19(magi)5(n)19(g)-1( acti)5(vi)5(ti)5(es. Local)5( )-20(aut)21(hori)5(t)1(i)5(e)-1(s )-20(c)23(an )-20(i)5(ssue abate)19(m)-4(ent)]TJ
+T*
+0.199 Tw
+[(noti)5(c)3(es. F)14(a)-1(i)5(l)5(u)-1(re t)21(o)-1( compl)5(y)3( c)23(onsti)5(tutes)23( an of)21(fence a)19(nd can )20(resul)5(t)1( i)5(n)19( )-20(fi)5(nes )-20(o)19(r)]TJ
+T*
+0.004 Tc
+[(i)6(m)-3(pri)6(s)4(onm)17(ent.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 372.32 Tm
+0.006 Tc
+-0.004 Tw
+[(Local)24( Gover)35(nm)15(ent R)8(e)22(for)15(m)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 346.16 Tm
+0.004 Tc
+0.018 Tw
+[(R)6(e)0(source )20(manag)20(ement)22( refo)20(rm i)6(n)0( N)26(e)0(w)6( Zeal)26(and w)6(a)0(s )20(rel)6(a)0(ted)20( to )-20(l)6(o)0(cal)6( )-20(g)20(o)0(vern)20(ment)]TJ
+T*
+0.003 Tc
+0.319 Tw
+[(refor)16(m)-4(, al)5(so occ)23(u)-1(rri)5(n)19(g)-1( i)5(n)-1( the)19( l)5(a)-1(te 19)19(80s, as l)25(o)-1(cal)5( )-20(gove)19(r)-4(nme)19(n)-1(t )-20(i)5(s)3( )-20(pri)25(m)-4(ari)5(l)5(y)]TJ
+0 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(responsi)6(b)0(l)6(e)0( )20(for i)26(m)-3(pl)6(eme)20(n)0(ti)6(ng r)17(e)0(sourc)24(e)0( ma)20(nagem)17(ent i)6(n)0(i)6(t)2(i)6(a)0(ti)6(v)24(e)0(s.)]TJ
+0 -2.32 TD
+0.078 Tw
+[(P)11(r)-3(i)6(o)0(r to r)17(e)0(for)17(m)-3(, l)6(o)0(cal)6( gov)24(ern)20(m)-3(ent i)6(n)0(cl)6(u)20(ded )20(more t)22(han )-20(8)20(00 )-20(l)6(o)0(cal)6( )-20(a)20(u)0(tho)20(r)-3(i)6(t)2(i)6(e)0(s )-20(and)]TJ
+0 -1.16 TD
+0.018 Tw
+[(speci)6(a)0(l)6( boar)17(ds and)20( el)6(ected )20(boro)20(ughs. )20(Fol)6(l)6(o)0(w)6(i)6(ng t)22(he en)20(actmen)20(t )-20(of )-20(a)20(m)-3(end)20(ments)]TJ
+T*
+0.078 Tw
+[(to the Loc)24(al)6( Gove)20(rnmen)20(t)2( A)11(c)4(t i)6(n)0( 198)20(9, l)6(o)0(cal)6( )-20(g)20(o)0(vern)20(ment )-20(h)20(ad )-20(be)20(en )-20(tr)17(ansfor)17(m)-3(ed)]TJ
+0 -1.14 TD
+0.003 Tc
+0.079 Tw
+[(i)5(n)-1(to )20(86 )20(l)5(o)-1(cal)5( )40(autho)19(ri)5(ti)5(es, )20(m)16(ade up)19( of 12 )20(regi)5(o)19(nal)5( counci)5(l)5(s)3( a)19(nd 74)19( l)5(o)-1(cal)5( counci)5(l)5(s)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(and fou)19(r)-4( uni)5(ta)19(ry auth)19(o)-1(ri)5(ti)5(es.)]TJ
+0 -2.32 TD
+0.519 Tw
+[(Governm)16(ent exp)19(e)-1(cted t)21(hese r)16(e)-1(for)16(m)-4(s to i)5(m)16(prove)19( the ef)21(fi)5(ci)5(ency of )-20(l)5(o)-1(c)23(a)-1(l)]TJ
+0 -1.16 TD
+0.02 Tw
+[(gover)-5(n)18(m)-5(ent, e)18(n)-2(sur)-5(e)18( clear)-5( )20(accounta)18(b)-2(ility and allow l)24(o)-2(cal gove)18(r)-5(nm)15(ent to f)20(o)-2(cus on)]TJ
+0 -1.14 TD
+0.259 Tw
+[(resourc)23(e)-1( )20(man)19(agem)16(ent deci)5(s)3(i)5(o)19(ns. B)10(y)3( red)19(u)-1(ci)5(ng th)19(e num)16(ber )20(of counci)5(l)5(s)3(, t)21(h)-1(e)]TJ
+0 -1.16 TD
+0.459 Tw
+[(refor)16(m)-4(s i)5(n)-1(cre)19(a)-1(sed ave)19(r)-4(age)19( counci)5(l)5( si)5(ze and )-20(i)5(n)-1(cr)16(eased thei)5(r )-20(ca)19(paci)5(t)1(y )-20(to)]TJ
+T*
+-0.001 Tw
+[(effecti)5(v)3(el)5(y anal)5(ys)23(e reso)19(urce )20(manag)19(emen)19(t i)5(ssues.)]TJ
+0 -2.32 TD
+0.059 Tw
+[(The )20(con)19(g)-1(l)5(o)-1(me)19(rati)5(on )40(of )20(the )40(rang)19(e )20(of )20(speci)25(a)-1(l)5(i)5(s)3(ed )20(bo)19(ards, f)21(o)-1(r i)5(ssues s)23(u)-1(ch as p)19(e)-1(st)]TJ
+0 -1.14 TD
+0.119 Tw
+[(control)5(,)1( )20(i)5(n)-1(t)21(o)-1( )20(si)5(ngl)5(e )20(co)19(unci)5(l)5( )20(uni)5(ts )40(may )20(hav)23(e al)5(so act)21(ed to s)23(e)-1(t the R)25(M)-4(A)10( up as a)]TJ
+0 -1.16 TD
+0.019 Tw
+[(l)5(i)5(ghtni)5(ng ro)19(d for)16( compl)5(a)-1(i)25(n)-1(ts and )20(frust)21(r)-4(ati)5(on. )20( W)7(here)19(a)-1(s i)5(n)-1( the )20(past seve)19(ral)5( bo)19(ards)]TJ
+ET
+endstream endobj 246 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 247 0 obj << /Type /Page /Parent 250 0 R /Resources 249 0 R /Contents 248 0 R >> endobj 248 0 obj << /Length 453 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(50)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.019 Tw
+[(may have )20(provi)5(d)-1(e)19(d)-1( conse)19(n)-1(ts for)16( one a)19(c)3(ti)5(vi)5(ty, afte)19(r the refo)19(rms )-20(on)19(e )-20(deal)5(t)21( )-20(w)5(i)5(t)1(h )-20(al)5(l)]TJ
+0 -1.16 TD
+0 Tw
+[(consents, th)18(us conce)18(n)-2(trati)4(n)18(g any co)18(mpl)4(a)-2(i)4(n)-2(ts.)]TJ
+ET
+endstream endobj 249 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 250 0 obj << /Type /Pages /Kids [ 247 0 R 105 0 R 253 0 R 256 0 R 259 0 R 262 0 R 265 0 R 268 0 R 107 0 R 273 0 R ] /Count 10 /Parent 151 0 R >> endobj 251 0 obj << /Length 5669 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(51)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.003 Tc
+-0.001 Tw
+[(Ap)-6(p)-6(e)-1(n)14(d)-6(ix )20(T)-6(w)1(o)14(:)-4( W)7(h)-6(y )20(an)14(d)-6( wh)-6(a)19(t)-4( sh)14(o)-6(u)14(ld)-6( we r)12(e)19(g)-6(u)-6(l)1(a)19(t)-4(e?)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.098 Tw
+[(\223The )40(purpos)24(e of t)22(h)0(i)6(s)4( A)11(c)4(t i)6(s)4( to pr)17(omote)20( the susta)20(i)6(nabl)6(e )20(mana)20(geme)20(n)0(t of n)20(a)0(tural)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(and physi)5(cal)5( )20(resou)19(r)-4(ces.\224 )20(\(S)10(ecti)5(on 5, R)25(M)-4(A)10( 1991)19(\))]TJ
+0 -2.32 TD
+0.099 Tw
+[(W)7(h)-1(y i)5(s)3( speci)5(a)-1(l)5( l)5(egi)5(sl)5(ati)5(o)-1(n)19( need)19(ed for)16( the manag)19(ement)21( )-20(of )-20(nat)21(ural)5( )-20(a)19(nd )-20(physi)5(cal)]TJ
+0 -1.16 TD
+0.004 Tc
+0.298 Tw
+[(resourc)24(e)0(s? T)15(he fun)20(dame)20(n)0(tal)6( pr)17(obl)6(em w)6(i)6(t)22(h reso)20(urces i)6(s)4( t)22(hat )-20(m)17(any )-20(of )-20(t)22(h)0(e)]TJ
+T*
+0.003 Tc
+0.279 Tw
+[(prope)19(rty )20(ri)5(gh)19(ts )20(are )40(not ful)5(l)5(y)3( )20(al)5(l)5(o)-1(cated )20(and en)19(force)19(d)-1(. U)5(n)-1(r)16(egul)5(ate)19(d)-1( reso)19(urce)]TJ
+0 -1.14 TD
+0.099 Tw
+[(markets w)5(o)19(ul)5(d l)5(ead )20(to i)5(neffi)5(ci)5(e)19(n)-1(cy beca)19(u)-1(se of )-20(ex)23(tern)19(al)5(i)5(t)1(i)5(e)-1(s. )-20( )-20(T)14(hey )-20(w)5(oul)5(d al)5(l)5(o)-1(w)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(some age)20(nts to cl)6(ai)26(m the )20(unal)6(l)6(o)0(cat)22(ed res)24(ources )20(for t)22(hei)6(r ow)6(n)20( use. Thi)6(s)4( )-20(i)6(s)4( )-20(an)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(undemoc)23(rati)5(c, i)5(n)-1(e)19(qui)5(tabl)5(e)19( w)5(a)-1(y to al)5(l)5(o)-1(c)23(a)-1(te r)16(e)-1(source)19(s that )-20(w)5(e)19(re )-20(p)19(r)-4(evi)5(ousl)5(y)3( )-20(h)19(e)-1(l)5(d)-1( )-20(i)5(n)]TJ
+T*
+0.099 Tw
+[(common.)21( Imp)19(e)-1(rfect i)5(n)19(for)16(m)-4(ati)5(on a)19(bout t)21(he effec)23(t)1(s of )-20(r)16(e)-1(sourc)23(e)-1( )-20(use )-20(i)5(s)3( )-20(t)21(he )-20(oth)19(e)-1(r)]TJ
+T*
+-0.001 Tw
+[(i)5(m)-4(porta)19(nt ma)19(rket fai)5(l)5(u)19(re i)5(n)-1( t)21(he al)5(l)5(o)-1(cati)25(on of )20(resou)19(r)-4(ces.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 553.04 Tm
+[(E)10(x)-1(ter)12(n)-6(alitie)19(s / I)21(n)-6(co)-6(m)12(p)-6(l)21(e)-1(te All)21(o)-6(ca)19(tio)14(n)-6( o)-6(f)16( P)10(r)12(o)-6(p)-6(e)-1(r)12(t)-4(y Ri)21(g)-6(h)-6(t)16(s)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 526.88 Tm
+0.239 Tw
+[(W)7(henever )20(p)19(r)-4(ope)19(rty )20(ri)5(g)19(h)-1(ts )20(ar)16(e i)5(n)-1(com)16(p)-1(l)5(e)-1(tel)5(y)3( de)19(fi)5(ned o)19(r)-4( enf)21(orced,)21( exter)16(nal)5(i)5(t)1(i)5(e)-1(s)]TJ
+T*
+0.199 Tw
+[(and publ)5(i)5(c)3( g)19(ood si)5(tu)19(ati)5(ons a)19(r)-4(i)5(s)3(e and)19( reso)19(urces ca)19(n be al)5(l)5(o)-1(c)23(a)-1(ted )-20(i)5(n)19(effi)5(ci)5(entl)5(y)]TJ
+0 -1.24 TD
+0.004 Tc
+0.138 Tw
+[(w)6(i)6(t)2(hout i)6(n)0(ter)17(v)4(enti)6(on.)]TJ
+10.08 0 0 10.08 207.84 501.085 Tm
+-0.008 Tc
+(21)Tj
+12 0 0 12 218.88 498.08 Tm
+0.003 Tc
+0.139 Tw
+[( A)10(n)-1( exter)16(nal)5(i)5(t)1(y ari)5(s)23(es )-20(w)5(henev)23(er )-20(an)19( )-20(i)5(ndi)5(vi)5(dual)5( does )-20(no)19(t)]TJ
+-9.96 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(bear )20(th)20(e ful)6(l)6( costs, )20(or r)17(e)0(cei)6(v)4(e th)20(e ful)6(l)6( be)20(nefi)6(t)2(s of )20(her ac)24(ti)6(on. )20(For ex)24(ampl)6(e )20(an)]TJ
+T*
+0.398 Tw
+[(unregul)6(a)20(t)2(ed )20(fac)24(t)2(ory )20(w)6(h)0(i)6(c)4(h)20( )20(emi)6(t)2(s )20(ef)22(fl)6(uent i)6(n)20(to a ri)6(v)24(e)0(r be)20(nefi)6(t)2(s f)22(r)-3(om w)6(a)0(st)22(e)]TJ
+T*
+0.003 Tc
+0.219 Tw
+[(di)5(sposal)5(, but )20(does n)19(o)-1(t bea)19(r the c)23(o)-1(st )-20(of dow)5(nstre)19(a)-1(m )-20(p)19(o)-1(l)5(l)5(u)-1(ti)5(on. )-20( )-20(E)10(x)3(te)19(rnal)5(i)5(t)1(i)5(e)-1(s)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(occur w)6(h)0(e)20(r)-3(ever )20(there)20( are i)26(n)0(compl)6(e)20(te pr)17(operty)24( ri)6(ghts )20(or mi)6(ssi)6(n)20(g)0( ma)20(rkets. )-20(I)22(t)2( )-20(i)6(s)]TJ
+0 -1.16 TD
+0.003 Tc
+0.039 Tw
+[(not )20(suffi)5(ci)5(ent )20(that p)19(r)-4(ope)19(rty ri)5(g)19(h)-1(ts exi)5(s)3(t, t)21(hey must)21( al)5(so be)19( transf)21(e)-1(rabl)25(e. N)5(egati)5(v)23(e)]TJ
+T*
+0 Tc
+0.042 Tw
+[(e)-4(x)0(te)-4(r)-7(n)-4(a)-4(litie)-4(s )20(will b)16(e)-4( o)-4(v)0(e)-4(r)13(p)-4(r)-7(o)-4(d)16(u)-4(c)0(e)-4(d)-4(,)-2( Q )20(r)-7(a)-4(th)-4(e)16(r)-7( th)-4(a)16(n)-4( Q*)9(, b)-4(e)-4(c)0(a)-4(u)-4(s)20(e)-4( th)-4(e)-4( )20(p)-4(r)-7(o)-4(d)16(u)-4(c)0(e)-4(r)-7( se)16(ts)]TJ
+T*
+0.004 Tc
+0.098 Tw
+[(pri)6(v)4(ate )20(m)17(a)0(rgi)6(n)20(al)6( )20(cost )20(eq)20(ual)6( )20(to th)20(e ma)20(rgi)6(nal)6( b)20(enefi)6(t)2( o)20(f)2( the ex)24(tern)20(al)6(i)6(t)2(y pro)20(duci)6(n)0(g)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(acti)5(vi)5(ty. P)10(r)-4(i)5(v)3(ate m)16(a)-1(rgi)5(nal)25( cost i)5(s)3( bel)5(ow)5( s)23(o)-1(ci)5(al)5( ma)19(rgi)5(nal)5( cos)23(t)1( )-20(\(taki)5(n)19(g )-20(i)5(n)-1(to )-20(acc)23(ount)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(sel)5(f)1(-prot)21(e)-1(cti)5(on / )20(adapti)5(v)3(e )20(behavi)5(o)19(ur\) )20(by the )20(amou)19(nt of th)19(e exte)19(rnal)5(i)5(t)1(y.)]TJ
+0 -22.56 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(21)Tj
+1.0952 -0.3095 TD
+0.015 Tw
+[( )-1429(F)-16(o)0(r)-8( m)-8(o)0(r)-8(e)0( de)24(t)-16(ailed dis)-8(c)-8(u)0(s)-8(s)-8(ion s)-8(ee B)-8(aum)-8(ol and O)-16(a)0(t)-16(e)0(s)16( \()-8(1975\))]TJ
+ET
+endstream endobj 252 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 253 0 obj << /Type /Page /Parent 250 0 R /Resources 255 0 R /Contents 254 0 R >> endobj 254 0 obj << /Length 8924 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(52)Tj
+/F3 1 Tf
+-34.32 57.3 TD
+0.006 Tc
+-0.004 Tw
+[(Fi)4(gur)15(e )20(6 O)4(ver)15(-)19(p)-3(r)15(odu)17(cti)24(on )20(of ex)22(ter)15(n)-3(al)4(i)24(t)-1(i)4(e)2(s)]TJ
+ET
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+1 i
+178.56 692.48 m
+178.56 551.12 l
+S
+0.24 w
+176.16 691.76 m
+180.96 691.76 l
+178.56 695.12 l
+176.16 691.76 l
+b*
+0.72 w
+178.56 551.12 m
+413.52 551.12 l
+S
+0.24 w
+412.56 553.52 m
+412.56 548.72 l
+416.16 551.12 l
+412.56 553.52 l
+b*
+0.96 w
+200.16 572.72 m
+365.76 623.12 l
+192.96 594.32 m
+365.76 695.12 l
+S
+0.72 w
+322.56 663.68 m
+322.56 611.36 l
+S
+0.24 w
+324.96 612.32 m
+320.16 612.32 l
+322.56 608.72 l
+324.96 612.32 l
+b*
+320.16 662.96 m
+324.96 662.96 l
+322.56 666.32 l
+320.16 662.96 l
+b*
+178.56 608.96 0.96 -0.48 re
+f*
+181.44 608.96 0.96 -0.48 re
+f*
+184.32 608.96 0.96 -0.48 re
+f*
+187.2 608.96 0.96 -0.48 re
+f*
+190.08 608.96 0.96 -0.48 re
+f*
+192.96 608.96 0.96 -0.48 re
+f*
+195.84 608.96 0.96 -0.48 re
+f*
+198.72 608.96 0.96 -0.48 re
+f*
+201.6 608.96 0.96 -0.48 re
+f*
+204.48 608.96 0.96 -0.48 re
+f*
+207.36 608.96 0.96 -0.48 re
+f*
+210.24 608.96 0.96 -0.48 re
+f*
+213.12 608.96 0.96 -0.48 re
+f*
+216 608.96 0.96 -0.48 re
+f*
+218.88 608.96 0.96 -0.48 re
+f*
+221.76 608.96 0.96 -0.48 re
+f*
+224.64 608.96 0.96 -0.48 re
+f*
+227.52 608.96 0.96 -0.48 re
+f*
+230.4 608.96 0.96 -0.48 re
+f*
+233.28 608.96 0.96 -0.48 re
+f*
+236.16 608.96 0.96 -0.48 re
+f*
+239.04 608.96 0.96 -0.48 re
+f*
+241.92 608.96 0.96 -0.48 re
+f*
+244.8 608.96 0.96 -0.48 re
+f*
+247.68 608.96 0.96 -0.48 re
+f*
+250.56 608.96 0.96 -0.48 re
+f*
+253.44 608.96 0.96 -0.48 re
+f*
+256.32 608.96 0.96 -0.48 re
+f*
+259.2 608.96 0.96 -0.48 re
+f*
+262.08 608.96 0.96 -0.48 re
+f*
+264.96 608.96 0.96 -0.48 re
+f*
+267.84 608.96 0.96 -0.48 re
+f*
+270.72 608.96 0.96 -0.48 re
+f*
+273.6 608.96 0.96 -0.48 re
+f*
+276.48 608.96 0.96 -0.48 re
+f*
+279.36 608.96 0.96 -0.48 re
+f*
+282.24 608.96 0.96 -0.48 re
+f*
+285.12 608.96 0.96 -0.48 re
+f*
+288 608.96 0.96 -0.48 re
+f*
+290.88 608.96 0.96 -0.48 re
+f*
+293.76 608.96 0.96 -0.48 re
+f*
+296.64 608.96 0.96 -0.48 re
+f*
+299.52 608.96 0.96 -0.48 re
+f*
+302.4 608.96 0.96 -0.48 re
+f*
+305.28 608.96 0.96 -0.48 re
+f*
+308.16 608.96 0.96 -0.48 re
+f*
+311.04 608.96 0.96 -0.48 re
+f*
+313.92 608.96 0.96 -0.48 re
+f*
+316.8 608.96 0.96 -0.48 re
+f*
+319.68 608.96 0.96 -0.48 re
+f*
+BT
+/F5 1 Tf
+12 0 0 12 157.92 603.68 Tm
+0 Tc
+0 Tw
+(P)Tj
+0 6.6 TD
+($)Tj
+19.2 -12.6 TD
+0.003 Tc
+0.379 Tw
+[(Quanti)5(t)1(y of)]TJ
+0 -1.18 TD
+0.004 Tc
+(output)Tj
+ET
+214.32 608.72 0.48 -0.96 re
+f*
+214.32 605.84 0.48 -0.96 re
+f*
+214.32 602.96 0.48 -0.96 re
+f*
+214.32 600.08 0.48 -0.96 re
+f*
+214.32 597.2 0.48 -0.96 re
+f*
+214.32 594.32 0.48 -0.96 re
+f*
+214.32 591.44 0.48 -0.96 re
+f*
+214.32 588.56 0.48 -0.96 re
+f*
+214.32 585.68 0.48 -0.96 re
+f*
+214.32 582.8 0.48 -0.96 re
+f*
+214.32 579.92 0.48 -0.96 re
+f*
+214.32 577.04 0.48 -0.96 re
+f*
+214.32 574.16 0.48 -0.96 re
+f*
+214.32 571.28 0.48 -0.96 re
+f*
+214.32 568.4 0.48 -0.96 re
+f*
+214.32 565.52 0.48 -0.96 re
+f*
+214.32 562.64 0.48 -0.96 re
+f*
+214.32 559.76 0.48 -0.96 re
+f*
+214.32 556.88 0.48 -0.96 re
+f*
+214.32 554 0.48 -0.96 re
+f*
+322.32 608.72 0.48 -0.96 re
+f*
+322.32 605.84 0.48 -0.96 re
+f*
+322.32 602.96 0.48 -0.96 re
+f*
+322.32 600.08 0.48 -0.96 re
+f*
+322.32 597.2 0.48 -0.96 re
+f*
+322.32 594.32 0.48 -0.96 re
+f*
+322.32 591.44 0.48 -0.96 re
+f*
+322.32 588.56 0.48 -0.96 re
+f*
+322.32 585.68 0.48 -0.96 re
+f*
+322.32 582.8 0.48 -0.96 re
+f*
+322.32 579.92 0.48 -0.96 re
+f*
+322.32 577.04 0.48 -0.96 re
+f*
+322.32 574.16 0.48 -0.96 re
+f*
+322.32 571.28 0.48 -0.96 re
+f*
+322.32 568.4 0.48 -0.96 re
+f*
+322.32 565.52 0.48 -0.96 re
+f*
+322.32 562.64 0.48 -0.96 re
+f*
+322.32 559.76 0.48 -0.96 re
+f*
+322.32 556.88 0.48 -0.96 re
+f*
+322.32 554 0.48 -0.96 re
+f*
+BT
+12 0 0 12 208.32 531.68 Tm
+0.002 Tc
+[(Q*)-7829(Q)]TJ
+13.8 7.2 TD
+-0.005 Tc
+[(Pr)-12(iv)-5(a)-9(t)-7(e)]TJ
+0 -1.18 TD
+0.001 Tc
+0.001 Tw
+[(m)14(a)-3(r)-6(g)-3(inal cost)]TJ
+0 8.38 TD
+0.003 Tc
+0.199 Tw
+[(S)10(o)-1(ci)5(al)5( m)16(a)-1(rgi)5(nal)]TJ
+0 -1.18 TD
+0.001 Tc
+(cost)Tj
+-1.8 -2.42 TD
+-0.001 Tc
+[(Exte)-5(r)-8(n)-5(a)-5(lity)]TJ
+ET
+0.72 w
+344.16 659.12 m
+324.24 639.44 l
+S
+0.24 w
+326.64 638.48 m
+323.28 641.6 l
+322.56 637.52 l
+326.64 638.48 l
+b*
+BT
+12 0 0 12 100.32 618.08 Tm
+0.005 Tc
+[(M)18(a)1(rgi)7(nal)]TJ
+0 -1.18 TD
+0.003 Tc
+-0.001 Tw
+[(B)10(enefi)5(t)1( =)]TJ
+-0.08 -9.48 TD
+0.004 Tc
+0.158 Tw
+[(E)11(v)4(en )20(w)6(here )20(p)20(r)-3(ope)20(rty )20(ri)6(g)20(h)0(ts exi)6(s)4(t, th)20(ey may )20(be un)20(enforc)24(eabl)6(e. A)11( p)20(u)0(re )20(publ)6(i)6(c)]TJ
+0 -1.14 TD
+0.003 Tc
+0.019 Tw
+[(good )20(i)5(s)3( )20(a )20(g)19(ood )20(th)19(at )20(i)5(t)1( )20(i)5(s)3( di)5(ffi)5(cul)5(t)21( to excl)5(ud)19(e peopl)25(e fro)19(m)-4( cons)23(umi)5(ng, )20(and th)19(at has)]TJ
+0 -1.16 TD
+0.004 Tc
+0.198 Tw
+[(a )20(zero )20(margi)6(n)20(al)6( cost of )20(provi)6(s)4(i)6(o)0(n)20( to an )20(addi)6(ti)6(on)20(al)6( pers)24(on. )20(For ex)24(ampl)6(e, )20(an)]TJ
+T*
+0.078 Tw
+[(attracti)6(ve )20(vi)6(ew)6( )40(from)17( )20(a )20(publ)6(i)6(c)4( )20(road.)22( W)8(hen a)20(n)0( i)6(ndi)6(vi)6(dual)6( )20(provi)6(des)24( a pu)20(bl)6(i)6(c)4( good,)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(by )20(for )20(exa)19(m)-4(pl)5(e )20(mai)5(n)-1(tai)5(n)-1(i)5(n)19(g an a)19(ttracti)5(ve)19( pro)19(perty, t)21(hey a)19(r)-4(e gen)19(erati)5(n)19(g posi)5(t)1(i)5(v)3(e)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(external)6(i)6(t)2(i)6(e)0(s )40(to )20(al)6(l)6( w)6(ho )20(enj)6(oy tha)20(t)2( publ)6(i)6(c)4( g)20(ood. )20(The )20(provi)6(d)0(e)20(r)-3( does)24( not )20(recei)6(v)4(e al)6(l)]TJ
+0 -1.14 TD
+0.003 Tc
+0.039 Tw
+[(the )20(bene)19(fi)5(ts. )20( )20(P)10(r)-4(ope)19(rty ri)5(g)19(h)-1(ts to )20(publ)5(i)5(c)3( goo)19(ds ar)16(e i)5(m)-4(possi)5(bl)25(e to en)19(force )20(because)]TJ
+0 -1.16 TD
+0.12 Tw
+[(people can)18(not be)18( exclude)18(d fr)-5(o)18(m)-5( using t)20(he goo)18(d. P)9(ublic go)18(ods will )-20(be )-20(u)18(nder)15(-)]TJ
+T*
+0.02 Tw
+[(pr)-5(oduce)18(d)-2( beca)18(u)-2(se the )20(pr)-5(od)18(ucer)-5( will set )20(pr)-5(ivate )20(m)-5(a)-2(r)15(g)-2(inal be)18(nefit eq)18(ual to )-20(p)18(r)-5(ivate)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(margi)6(nal)6( )20(c)24(o)0(st. )20( )20(For p)20(ubl)6(i)6(c)4( goo)20(ds, soci)6(al)6( m)17(a)0(rgi)6(nal)6( )20(benefi)6(t)22( i)6(s)4( the su)20(m of al)6(l)6( )20(pri)6(v)4(ate)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(margi)5(nal)5( )20(benefi)5(t)1(s,)21( not o)19(n)-1(l)5(y)3( the p)19(r)-4(oduc)23(er\222)5(s)3( be)19(nefi)5(t. The )-20(un)19(der)16(-provi)5(si)5(o)19(n)-1( )-20(si)5(tuati)5(o)19(n)]TJ
+0 -1.14 TD
+0.219 Tw
+[(i)5(s)3( )20(even )20(w)5(o)-1(rse)19( )20(i)5(f)1( ther)16(e ar)16(e sever)16(a)-1(l)5( pote)19(n)-1(ti)5(al)5( pr)16(ovi)5(ders w)5(h)19(o each )20(rel)5(y)3( on)19( the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.278 Tw
+[(others\222)6( )20(p)20(r)-3(ovi)6(s)4(i)6(on )40(rathe)20(r)-3( )20(than)20( provi)6(d)0(i)6(n)20(g the )20(good t)22(hemsel)6(v)24(es. W)8(i)6(th a l)6(a)20(rge)]TJ
+T*
+0.002 Tc
+0 Tw
+[(num)-5(be)18(r)-5( of po)18(tential p)18(r)-5(ovide)18(r)-5(s, alm)-5(o)-2(s)22(t)0( no p)18(ublic goo)18(d will be pr)15(oduced)18(.)]TJ
+0 -2.32 TD
+0.179 Tw
+[(W)7(here an )20(acti)5(vi)5(ty or )20(good )20(has pri)5(v)3(a)19(t)1(e be)19(nefi)5(t)1(s as w)5(e)-1(l)5(l)5( as)23( publ)5(i)5(c)3(, t)21(he )-20(pri)5(v)3(a)19(t)1(e)]TJ
+0 -1.14 TD
+0.219 Tw
+[(benefi)5(t)1(s m)16(a)-1(y be su)19(ffi)5(ci)5(ent th)19(at at th)19(e l)5(e)-1(vel)5( of)21( pri)5(v)3(ate)19( provi)5(s)3(i)5(o)19(n the )20(margi)25(nal)]TJ
+0 -1.16 TD
+0.039 Tw
+[(publ)5(i)5(c)3( val)5(ue i)5(s)3( ze)19(ro. I)21(n)-1( )-20(thi)5(s)3( )-20(case ther)16(e )-20(i)5(s)3( )-20(no )-20(del)5(i)25(berat)21(e )-20(pr)16(oducti)5(on of )-20(the publ)5(i)5(c)]TJ
+T*
+0.119 Tw
+[(good but)21( an effi)5(ci)5(e)19(n)-1(t l)5(e)-1(vel)5( i)5(s)3( coi)25(n)-1(ci)5(dental)5(l)5(y)3( p)19(r)-4(oduc)23(ed. )20(For )-20(ex)23(ampl)5(e,)21( )-20(attr)16(acti)5(ve)]TJ
+T*
+-0.001 Tc
+0.203 Tw
+[(r)-8(u)-5(r)-8(a)-5(l vie)-5(w)1(s will b)-5(e)-5( w)21(e)-5(ll p)-5(r)-8(o)-5(v)-1(id)15(e)-5(d)-5( in)-5( a)15(r)-8(e)-5(a)-5(s)-1( wh)-5(e)15(r)-8(e)-5( fa)15(r)-8(m)-8(i)1(n)-5(g)15( is p)-5(r)-8(o)-5(f)-3(it)17(a)-5(b)-5(l)1(e)-5(;)-3( )-20(n)15(a)-5(tive)]TJ
+T*
+0.243 Tw
+[(fo)-5(r)-8(e)-5(st )20(co)-5(ve)15(r)-8( )20(will )20(b)-5(e)-5( p)15(r)-8(iva)-5(t)-3(e)-5(l)1(y p)15(r)-8(o)-5(v)-1(id)-5(e)-5(d)15( in)-5( a)-5(r)12(e)-5(a)-5(s)-1( wh)-5(e)15(r)-8(e)-5( th)-5(e)-5( c)19(u)-5(r)-8(r)12(e)-5(n)-5(t)-3( e)-5(c)-1(o)15(n)-5(o)-5(m)-8(ic)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(val)5(ue fro)19(m)-4( usi)5(ng t)21(he l)5(and)19( for )20(non-f)21(o)-1(rest )20(acti)5(vi)5(ti)5(es i)5(s)3( zer)16(o)-1(.)]TJ
+ET
+endstream endobj 255 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 256 0 obj << /Type /Page /Parent 250 0 R /Resources 258 0 R /Contents 257 0 R >> endobj 257 0 obj << /Length 9295 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(53)Tj
+/F3 1 Tf
+-34.32 57.3 TD
+0.008 Tc
+-0.006 Tw
+[(Fi)6(gur)17(e )20(7 U)10(n)19(der)17(-)1(pr)17(ovi)26(s)4(i)6(o)19(n o)19(f)1( P)15(ubl)6(i)26(c)4( G)6(o)19(ods)]TJ
+ET
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+1 i
+171.36 692.72 m
+171.36 551.36 l
+S
+0.24 w
+168.96 691.76 m
+173.76 691.76 l
+171.36 695.36 l
+168.96 691.76 l
+b*
+0.72 w
+171.36 551.36 m
+406.32 551.36 l
+S
+0.24 w
+405.36 553.76 m
+405.36 548.96 l
+408.96 551.36 l
+405.36 553.76 l
+b*
+171.36 609.2 0.96 -0.48 re
+f*
+174.24 609.2 0.96 -0.48 re
+f*
+177.12 609.2 0.96 -0.48 re
+f*
+180 609.2 0.96 -0.48 re
+f*
+182.88 609.2 0.96 -0.48 re
+f*
+185.76 609.2 0.96 -0.48 re
+f*
+188.64 609.2 0.96 -0.48 re
+f*
+191.52 609.2 0.96 -0.48 re
+f*
+194.4 609.2 0.96 -0.48 re
+f*
+197.28 609.2 0.96 -0.48 re
+f*
+200.16 609.2 0.96 -0.48 re
+f*
+203.04 609.2 0.96 -0.48 re
+f*
+205.92 609.2 0.96 -0.48 re
+f*
+208.8 609.2 0.96 -0.48 re
+f*
+211.68 609.2 0.96 -0.48 re
+f*
+214.56 609.2 0.96 -0.48 re
+f*
+217.44 609.2 0.96 -0.48 re
+f*
+220.32 609.2 0.96 -0.48 re
+f*
+223.2 609.2 0.96 -0.48 re
+f*
+226.08 609.2 0.96 -0.48 re
+f*
+228.96 609.2 0.96 -0.48 re
+f*
+231.84 609.2 0.96 -0.48 re
+f*
+234.72 609.2 0.96 -0.48 re
+f*
+237.6 609.2 0.96 -0.48 re
+f*
+240.48 609.2 0.96 -0.48 re
+f*
+243.36 609.2 0.96 -0.48 re
+f*
+246.24 609.2 0.96 -0.48 re
+f*
+249.12 609.2 0.96 -0.48 re
+f*
+252 609.2 0.96 -0.48 re
+f*
+254.88 609.2 0.96 -0.48 re
+f*
+257.76 609.2 0.96 -0.48 re
+f*
+260.64 609.2 0.96 -0.48 re
+f*
+263.52 609.2 0.96 -0.48 re
+f*
+266.4 609.2 0.96 -0.48 re
+f*
+269.28 609.2 0.96 -0.48 re
+f*
+272.16 609.2 0.96 -0.48 re
+f*
+275.04 609.2 0.96 -0.48 re
+f*
+277.92 609.2 0.96 -0.48 re
+f*
+280.8 609.2 0.96 -0.48 re
+f*
+283.68 609.2 0.96 -0.48 re
+f*
+286.56 609.2 0.96 -0.48 re
+f*
+289.44 609.2 0.96 -0.48 re
+f*
+292.32 609.2 0.96 -0.48 re
+f*
+295.2 609.2 0.96 -0.48 re
+f*
+298.08 609.2 0.96 -0.48 re
+f*
+300.96 609.2 0.96 -0.48 re
+f*
+303.84 609.2 0.96 -0.48 re
+f*
+306.72 609.2 0.96 -0.48 re
+f*
+309.6 609.2 0.96 -0.48 re
+f*
+312.48 609.2 0.96 -0.48 re
+f*
+BT
+/F5 1 Tf
+12 0 0 12 150.72 603.68 Tm
+0 Tc
+0 Tw
+(P)Tj
+0 6.6 TD
+($)Tj
+19.2 -12.6 TD
+0.003 Tc
+0.379 Tw
+[(Quanti)5(t)1(y of)]TJ
+0 -1.16 TD
+0.004 Tc
+[(publ)6(i)6(c)4( )]TJ
+ET
+q
+381.12 516.08 62.88 27.12 re
+W n
+BT
+12 0 0 12 415.922 517.76 Tm
+0 Tc
+0 Tw
+(g)Tj
+ET
+Q
+BT
+12 0 0 12 422.642 517.76 Tm
+(ood)Tj
+ET
+207.12 608.96 0.48 -0.96 re
+f*
+207.12 606.08 0.48 -0.96 re
+f*
+207.12 603.2 0.48 -0.96 re
+f*
+207.12 600.32 0.48 -0.96 re
+f*
+207.12 597.44 0.48 -0.96 re
+f*
+207.12 594.56 0.48 -0.96 re
+f*
+207.12 591.68 0.48 -0.96 re
+f*
+207.12 588.8 0.48 -0.96 re
+f*
+207.12 585.92 0.48 -0.96 re
+f*
+207.12 583.04 0.48 -0.96 re
+f*
+207.12 580.16 0.48 -0.96 re
+f*
+207.12 577.28 0.48 -0.96 re
+f*
+207.12 574.4 0.48 -0.96 re
+f*
+207.12 571.52 0.48 -0.96 re
+f*
+207.12 568.64 0.48 -0.96 re
+f*
+207.12 565.76 0.48 -0.96 re
+f*
+207.12 562.88 0.48 -0.96 re
+f*
+207.12 560 0.48 -0.96 re
+f*
+207.12 557.12 0.48 -0.96 re
+f*
+207.12 554.24 0.48 -0.96 re
+f*
+315.12 608.96 0.48 -0.96 re
+f*
+315.12 606.08 0.48 -0.96 re
+f*
+315.12 603.2 0.48 -0.96 re
+f*
+315.12 600.32 0.48 -0.96 re
+f*
+315.12 597.44 0.48 -0.96 re
+f*
+315.12 594.56 0.48 -0.96 re
+f*
+315.12 591.68 0.48 -0.96 re
+f*
+315.12 588.8 0.48 -0.96 re
+f*
+315.12 585.92 0.48 -0.96 re
+f*
+315.12 583.04 0.48 -0.96 re
+f*
+315.12 580.16 0.48 -0.96 re
+f*
+315.12 577.28 0.48 -0.96 re
+f*
+315.12 574.4 0.48 -0.96 re
+f*
+315.12 571.52 0.48 -0.96 re
+f*
+315.12 568.64 0.48 -0.96 re
+f*
+315.12 565.76 0.48 -0.96 re
+f*
+315.12 562.88 0.48 -0.96 re
+f*
+315.12 560 0.48 -0.96 re
+f*
+315.12 557.12 0.48 -0.96 re
+f*
+315.12 554.24 0.48 -0.96 re
+f*
+BT
+12 0 0 12 201.12 531.68 Tm
+8.222 Tc
+[(QQ)8220(*)]TJ
+11.6 3 TD
+0.004 Tc
+-0.002 Tw
+[(P)11(r)-3(i)6(v)4(ate m)17(a)0(rgi)6(nal)]TJ
+-0.58 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(benefi)5(t)1( to pr)16(oducer)]TJ
+-0.64 4.76 TD
+[(M)16(a)-1(rgi)5(nal)5( S)10(o)-1(ci)5(al)5( B)-10(enefi)5(t)]TJ
+ET
+0.96 w
+178.56 623.36 m
+329.76 558.56 l
+207.36 702.56 m
+344.16 587.36 l
+S
+BT
+12 0 0 12 100.32 618.08 Tm
+0.005 Tc
+[(M)18(a)1(rgi)7(nal)]TJ
+0 -1.16 TD
+0.001 Tc
+0.001 Tw
+(Cost =)Tj
+-0.08 -9.5 TD
+0.004 Tc
+0.038 Tw
+[(A)11( )20(rel)6(a)0(ted )20(si)6(tua)20(t)2(i)6(on )20(i)6(s)4( tha)20(t)2( of \223c)24(omm)17(on pr)17(oper)17(ty reso)20(urces)24(\224)-3(. A)11( com)17(m)-3(on p)20(r)-3(ope)20(rty)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(resourc)23(e)-1( i)5(s)3( one t)21(hat m)16(any i)5(ndi)5(vi)5(du)19(al)5(s can p)19(a)-1(rti)5(a)-1(l)5(l)5(y)3( co)19(ntrol)5(,)1( f)21(o)-1(r exa)19(m)-4(pl)5(e a)19( fi)5(shery)]TJ
+T*
+0.239 Tw
+[(w)5(i)5(t)1(h many fi)5(sh)19(erme)19(n. W)7(hen )20(an i)5(ndi)5(vi)5(d)19(ual)5( uses t)21(he )-20(res)23(ource he )-20(cr)16(eates )-20(a)]TJ
+0 -1.14 TD
+0.004 Tc
+0.298 Tw
+[(negati)6(v)4(e )-20(ext)22(e)0(rnal)6(i)6(t)2(y for )-20(al)6(l)6( other users. )-20(The)20( )-20(negati)6(v)24(e )-40(exte)20(rnal)6(i)6(t)2(y )-40(l)6(eads)24( )-40(to)]TJ
+0 -1.16 TD
+0.218 Tw
+[(overuse o)20(f)2( the )20(resou)20(r)-3(ce, an)20(d an i)6(n)20(effi)6(ci)6(ent o)20(u)0(tcome)20( )-20(for )-20(t)22(he )-20(w)6(hol)6(e)20( )-20(grou)20(p )-20(of)]TJ
+0 -1.26 TD
+-0.002 Tw
+[(common )20(ow)6(ners.)22( Thi)6(s)4( i)6(s)4( k)24(now)6(n as t)22(he \221)6(t)2(ra)20(gedy of)22( the co)20(mmons\222)26(.)]TJ
+10.08 0 0 10.08 446.64 422.605 Tm
+-0.008 Tc
+(22)Tj
+12 0 2.551 12 99.36 392 Tm
+0.004 Tc
+[(\223P)11(ri)6(vate\224 sol)26(u)0(ti)6(ons fo)20(r exte)20(rnal)6(i)6(t)2(y p)20(r)-3(obl)6(e)20(m)-3(s)]TJ
+12 0 0 12 99.36 364.16 Tm
+0.003 Tc
+0.119 Tw
+[(Incompl)5(e)-1(te)19(, une)19(nforce)19(abl)5(e o)19(r)-4( com)16(m)-4(on p)19(r)-4(ope)19(rty ri)5(g)19(h)-1(ts )-20(l)5(ead )-20(t)21(o)-1( )-20(i)5(neffi)5(ci)5(ency)23( )-20(i)5(n)-1( )-20(a)]TJ
+0 -1.16 TD
+0.259 Tw
+[(purel)5(y i)5(ndi)5(vi)5(d)19(ual)5(i)5(s)3(ti)5(c w)5(o)-1(rl)5(d. )20( D)5(oes thi)5(s)3( )20(mean t)21(hat gov)23(ern)19(m)-4(ent i)5(s)3( n)19(eeded)19( to)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(control)6( th)20(ese res)24(ources)24(?)0( Th)20(e exi)6(s)4(tenc)24(e of )-20(a )-20(ma)20(rke)20(t)2( )-20(fai)6(l)6(u)0(r)17(e)0( )-20(does not )-20(m)17(ean )-20(th)20(at)]TJ
+0 -1.14 TD
+0.038 Tw
+[(govern)20(m)-3(ent sh)20(oul)6(d r)17(egul)6(ate.)22( Gove)20(rnme)20(nt may )20(not be)20( )-20(abl)6(e )-20(to)20( )-20(sol)6(v)4(e )-20(the)20( )-20(mark)24(et)]TJ
+0 -1.16 TD
+0.258 Tw
+[(fai)6(l)6(u)0(re, )20(an)20(d coul)6(d i)26(n)0(trod)20(uce fai)6(l)6(u)20(res of i)6(t)2(s )20(ow)6(n, \223g)20(overn)20(m)-3(ent )20(fai)6(l)6(u)0(res)24(\224)-3( w)6(h)0(i)6(c)4(h)]TJ
+T*
+0.178 Tw
+[(coul)6(d exace)20(r)-3(bate )20(the p)20(r)-3(obl)6(em)17(. )-20( )-20(One argu)20(ment agai)6(nst )-20(i)6(n)0(t)22(ensi)6(v)4(e )-20(g)20(o)0(vern)20(ment)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(i)5(n)-1(terventi)5(o)19(n )20(i)5(s)3( that )20(al)5(l)5( that i)5(s)3( n)19(e)-1(cessary)23( i)5(s)3( to defi)25(ne the)19( prop)19(erty )20(ri)5(ghts, a)19(n)-1(d)]TJ
+T*
+0.02 Tw
+[(negotiation)18( and t)20(he com)15(m)-5(on law )-20(sys)22(tem)-5( )-20(will )-20(allocat)20(e)-2( )-20(r)-5(e)-2(s)22(our)-5(ces efficiently. )-20( T)-7(h)-2(is)]TJ
+0 -1.14 TD
+0.004 Tc
+0.218 Tw
+[(argum)17(ent )20(i)6(s)4( )20(bas)24(ed )20(on t)22(he C)6(oas)24(e The)20(o)0(re)20(m \(C)6(oas)24(e, 196)20(0\) w)6(h)0(i)6(c)4(h s)24(t)2(ates th)20(at)]TJ
+0 -1.16 TD
+0.238 Tw
+[(w)6(hen pro)20(perty )20(ri)6(ghts a)20(r)-3(e ful)6(l)6(y)4( )20(al)6(l)6(o)0(cated, )20(and t)22(r)-3(ansfe)20(rabl)6(e, )20(and th)20(ere )20(are n)20(o)]TJ
+T*
+0 Tc
+0.102 Tw
+[(tr)-7(a)-4(n)-4(s)0(a)-4(c)0(tio)-4(n)16( )20(co)-4(sts, )20(r)13(e)-4(so)-4(u)-4(r)-7(c)20(e)-4(s )20(will )20(b)-4(e)-4( a)-4(llo)-4(ca)16(te)-4(d)-4( e)-4(fficie)16(n)-4(tly r)-7(e)16(g)-4(a)-4(r)-7(d)-4(l)2(e)-4(s)0(s)20( o)-4(f)-2( th)-4(e)16( in)-4(itia)-4(l)]TJ
+T*
+0.001 Tc
+0.001 Tw
+[(allocation. )20(T)-8(he initial )20(allocation will still hav)21(e distr)-6(i)3(b)17(u)-3(tional ef)19(fects.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.199 Tw
+[(The C)5(oase)19( The)19(o)-1(re)19(m sugg)19(ests that )20(many )20(extern)19(al)5(i)5(t)1(y i)5(ssues can)19( be )-20(r)16(e)-1(sol)5(v)3(ed)]TJ
+0 -1.16 TD
+0.119 Tw
+[(pri)5(v)3(atel)5(y. In)19( fact thi)5(s)3( i)5(s)3( w)25(hat occu)19(rs w)5(hen)19(ever a)19( )-20(new)5( )-20(m)16(a)-1(rket )-20(i)5(s)3( )-20(c)23(r)-4(eate)19(d)-1( )-20(for a)]TJ
+T*
+0.139 Tw
+[(good tha)19(t)1( w)5(a)-1(s pr)16(evi)5(ousl)5(y)3( outsi)25(de the )20(mark)23(et, e.g)19(.: the )20(recent)21( )-20(devel)5(op)19(ment of)]TJ
+T*
+0.28 Tw
+[(pr)-5(ivate )20(r)15(ubbish )20(collec)22(t)0(ion in Wellingt)20(on. )20(T)-7(hese p)18(r)-5(ivate s)22(o)-2(lutions still r)15(equir)-5(e)]TJ
+T*
+0.179 Tw
+[(som)-4(e)-1( )20(gove)19(r)-4(nm)16(ent )20(involve)19(m)-4(ent,)21( gover)16(nm)-4(en)19(t still needs)23( to defi)25(ne and)19( enfo)19(r)-4(ce)]TJ
+0 -2.14 TD
+0 Tw
+( )Tj
+ET
+0 J 0.72 w
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(22)Tj
+1.0952 -0.3095 TD
+1.444 Tw
+[( Har)-8(din )1428(\()-8(1968\))]TJ
+ET
+endstream endobj 258 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 259 0 obj << /Type /Page /Parent 250 0 R /Resources 261 0 R /Contents 260 0 R >> endobj 260 0 obj << /Length 8749 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(54)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.179 Tw
+[(prope)19(rty ri)5(gh)19(ts, but i)5(t)1( i)5(s)3( a )-20(very uni)5(ntr)16(u)-1(si)5(ve )-20(form)16( )-20(of regul)5(a)19(t)1(i)5(on. )-20(In the )-20(r)16(ubbi)5(sh)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(col)5(l)5(e)-1(cti)5(on case, t)21(he gov)23(ern)19(m)-4(ent est)21(abl)5(i)5(s)3(hes pr)16(ope)19(rty ri)5(g)19(h)-1(ts to th)19(e use )20(of l)5(and )-20(f)21(o)-1(r)]TJ
+T*
+0.004 Tc
+0.298 Tw
+[(di)6(sposal)6( by ba)20(nni)6(ng d)20(u)0(mpi)6(n)20(g of r)17(ubbi)6(sh, )20(and ot)22(her f)22(o)0(rms )20(of )-20(i)6(nap)20(prop)20(ri)6(ate)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(di)5(sposal)5(. )20( )20(T)14(he l)5(i)5(m)-4(i)5(t)1(s to)19( the us)23(e of p)19(r)-4(i)5(v)3(ate sol)25(u)-1(ti)5(ons de)19(pend )20(on the)19( exi)5(s)3(tence )20(of)]TJ
+0 -1.14 TD
+0 Tc
+0.162 Tw
+[(tr)-7(a)-4(n)-4(s)0(a)-4(c)0(tio)-4(n)16( co)-4(sts, a)16(n)-4(d)-4( th)-4(e)-4( )20(a)-4(b)-4(ility to)-4( fu)-4(lly )20(a)-4(llo)-4(ca)-4(te)-4( a)16(n)-4(d)-4( e)-4(n)-4(f)18(o)-4(r)-7(ce)-4( p)-4(r)-7(o)-4(p)16(e)-4(r)-7(ty )-20(r)-7(i)22(g)-4(h)-4(t)-2(s.)]TJ
+0 -1.16 TD
+0.003 Tc
+0.259 Tw
+[(W)7(hen )20(can )20(th)19(e )20(R)5(e)-1(sou)19(r)-4(ce Ma)19(nage)19(ment A)10(c)3(t\222)5(s r)16(o)-1(l)5(e)-1( be l)5(i)5(m)-4(i)5(t)21(ed to )20(defi)5(n)-1(i)5(ng )20(and)]TJ
+T*
+0.004 Tc
+-0.022 Tw
+[(enforci)6(ng prop)20(erty ri)6(ghts?)]TJ
+0 -2.32 TD
+0.003 Tc
+0.219 Tw
+[(Transac)23(ti)5(on costs )20(ari)5(s)3(e p)19(r)-4(i)5(m)-4(a)19(r)-4(i)5(l)5(y)3( from)16( i)5(n)-1(for)16(m)-4(ati)5(on )20(asymm)16(e)-1(tri)5(e)-1(s a)19(nd costs )20(of)]TJ
+0 -1.14 TD
+0.139 Tw
+[(coordi)5(nati)5(o)19(n )20(am)16(ong )20(l)5(a)19(rge )20(g)19(r)-4(oups. )40( If the \221)5(v)3(i)5(c)3(ti)5(m)16(\222)5( of an)19( exter)16(nal)5(i)5(t)1(y i)5(s)3( una)19(bl)5(e to)]TJ
+0 -1.16 TD
+0.059 Tw
+[(observe i)5(t)1(s )20(prod)19(ucti)5(on, sh)19(e i)5(s)3( una)19(bl)5(e to e)19(n)-1(force)19( any ag)19(ree)19(m)-4(ent a)19(bout t)21(he )-20(l)5(e)-1(vel)]TJ
+T*
+0.119 Tw
+[(of prod)19(ucti)5(on. I)21(f)1( ei)5(the)19(r)-4( the vi)5(cti)25(m)-4( or )20(pol)5(l)5(u)-1(ter)16( cannot)21( obse)19(r)-4(ve the )20(othe)19(r\222)5(s )-20(costs)]TJ
+T*
+0.019 Tw
+[(and ben)19(efi)5(t)1(s fro)19(m)-4( the )20(pol)5(l)5(u)-1(ti)5(on,)21( barg)19(a)-1(i)5(n)-1(i)5(ng t)21(o)-1( fi)5(nd th)19(e effi)5(ci)5(ent)21( l)5(e)-1(vel)5( i)5(s)3( )-20(costl)5(y)3( )-20(a)19(n)-1(d)]TJ
+0 -1.24 TD
+0.119 Tw
+[(l)5(i)5(k)3(el)5(y to end u)19(p)-1( at an)19( i)5(neffi)5(ci)5(ent)21( l)5(e)-1(vel)5(.)]TJ
+10.08 0 0 10.08 304.8 567.565 Tm
+-0.008 Tc
+(23)Tj
+12 0 0 12 315.84 564.56 Tm
+0.003 Tc
+0.139 Tw
+[( )20( If transac)23(ti)5(ons a)19(r)-4(e costl)5(y)3(, t)21(he use )20(of)]TJ
+-18.04 -1.16 TD
+-0.001 Tc
+0.103 Tw
+[(r)-8(e)-5(so)-5(u)-5(r)-8(c)19(e)-5(s )20(will b)-5(e)-5( b)-5(i)1(a)-5(s)-1(e)15(d)-5( to)-5(wa)-5(r)12(d)-5( th)-5(e)-5( in)-5(i)21(t)-3(ia)-5(l a)-5(llo)-5(ca)-5(tio)-5(n)15(, wh)-5(ich)-5( th)-5(e)15(n)-5( h)-5(a)-5(s)-1( )20(e)-5(fficie)-5(n)-5(c)-1(y)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(as w)5(e)-1(l)5(l)5( as di)5(stri)5(b)19(u)-1(ti)5(onal)5( ef)21(fects.)]TJ
+0 -2.32 TD
+0.219 Tw
+[(C)5(o)-1(sts )20(of )20(coo)19(r)-4(di)5(nati)5(o)-1(n)19( )20(are )20(l)25(o)-1(w)5( )20(w)5(hen a)19(n)-1( exte)19(rnal)5(i)5(t)1(y i)5(s)3( l)5(i)5(m)-4(i)5(t)1(e)19(d)-1( to a v)23(e)-1(ry sm)16(al)5(l)]TJ
+0 -1.14 TD
+0.359 Tw
+[(numbe)19(r of p)19(r)-4(oduce)19(r)-4(s and)19( vi)5(cti)5(m)-4(s w)5(ho )20(are g)19(eogr)16(aphi)5(cal)5(l)5(y)3(, te)19(mpo)19(r)-4(al)5(l)5(y)3( and)]TJ
+0 -1.16 TD
+0.219 Tw
+[(soci)5(al)5(l)5(y)3( cl)5(osel)5(y l)5(i)5(n)-1(ked. W)7(h)19(en a p)19(o)-1(l)5(l)5(u)-1(tant a)19(ffects a l)25(a)-1(rge numb)19(e)-1(r )-20(of peopl)5(e,)]TJ
+T*
+0.28 Tw
+[(com)-5(e)-2(s fr)15(om)-5( seve)18(r)-5(a)-2(l sou)18(r)-5(ces, o)18(r)-5( has )20(effects ove)18(r)-5( a num)-5(b)18(e)-2(r)-5( )-20(of )-20(y)22(ear)-5(s, )-20(it )-20(is)]TJ
+T*
+0.379 Tw
+[(unreaso)19(nabl)5(e t)21(o)-1( expect )20(al)5(l)5( the )-20(af)21(fected parti)5(es to )-20(ne)19(goti)5(a)-1(te )-20(s)23(u)-1(ccessful)5(l)5(y)3(.)]TJ
+T*
+-0.001 Tw
+[(P)10(r)-4(ovi)5(d)-1(i)5(ng coo)19(r)-4(di)5(nati)5(o)-1(n)19( i)5(s)3( i)5(t)1(sel)5(f)1( a p)19(ubl)5(i)5(c)3( goo)19(d and )20(hence i)5(s)3( u)19(nder)16(-pr)16(o)-1(vi)5(ded.)]TJ
+0 -2.3 TD
+0.04 Tw
+[(T)-7(he )20(ability o)18(f)0( gove)18(r)-5(nm)-5(e)18(n)-2(t to f)20(u)-2(lly allocate )20(and en)18(for)-5(c)2(e )20(pr)-5(op)18(er)-5(ty r)-5(i)24(ghts co)18(m)-5(e)-2( into)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(pl)6(ay for co)20(mmo)20(n reso)20(urces a)20(nd pu)20(bl)6(i)6(c)4( goods.)22( )-20( )-20(S)11(o)0(me )-20(g)20(oods )-20(i)6(n)0(h)20(e)0(rentl)6(y)4( )-20(c)24(annot)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(be al)5(l)5(o)-1(cated)19( becaus)23(e of th)19(ei)5(r )-20(physi)5(cal)5( charac)23(teri)5(sti)5(cs \(e.g.: )-20(fi)5(s)23(h)-1( )-20(that mi)5(grat)21(e, )-20(oi)5(l)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(fi)6(el)6(ds and g)20(r)-3(oun)20(d w)6(a)0(ter,)22( ai)6(r\))17(. Th)20(ese may)24( )-20(be )-20(m)17(o)0(st )-20(app)20(rop)20(r)-3(i)6(a)0(tel)6(y)4( )-20(tr)17(eated and)]TJ
+0 -1.14 TD
+0.338 Tw
+[(regul)6(ate)20(d)0( as co)20(mmon )20(prop)20(erty. P)11(s)4(eu)20(do p)20(r)-3(oper)17(ty ri)6(ghts)24( can be)20( )-20(al)6(l)6(o)0(cate)20(d)]TJ
+0 -1.16 TD
+0.138 Tw
+[(through)20( )20(the )20(c)24(r)-3(eati)6(on )20(of tr)17(adeabl)6(e)20( per)17(mi)6(ts for)17( use. S)11(o)20(me l)6(e)0(vel)6( of)22( gove)20(r)-3(nmen)20(t)]TJ
+T*
+0.218 Tw
+[(must enfo)20(r)-3(ce th)20(ese. )20(Ther)17(e are)20( few)6( i)6(n)0(cen)20(t)2(i)6(v)4(es for )20(per)17(mi)6(t )-20(hol)6(de)20(rs )-20(to ensure)]TJ
+T*
+0.158 Tw
+[(enforce)20(ment t)22(h)0(rou)20(gh no)20(rmal)6( l)6(e)0(g)20(a)0(l)6( chan)20(nel)6(s. T)15(he gov)24(ernm)17(ent can)20(not )-20(cha)20(r)-3(ge)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(di)5(rectl)5(y)3( )20(for)16( )20(the )20(us)23(e )20(of )20(pu)19(bl)5(i)5(c)3( goods)23( becaus)23(e i)5(t)1( i)5(s)3( i)5(m)-4(possi)25(bl)5(e to st)21(op peo)19(pl)5(e usi)5(n)-1(g)]TJ
+0 -1.14 TD
+0.004 Tc
+0.018 Tw
+[(them an)20(d henc)24(e i)6(m)-3(possi)6(bl)26(e to )-20(en)20(force paymen)20(t. )-20( )-20(Gov)24(e)0(rnm)17(ent )-20(m)17(u)0(st )-20(re)20(gul)6(ate on)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(the provi)5(s)3(i)5(o)19(n si)5(de n)19(o)-1(t the c)23(onsum)16(pti)5(on si)5(de.)]TJ
+0 -2.32 TD
+0.239 Tw
+[(In some cas)23(e)-1(s com)16(m)-4(uni)5(ti)5(es )20(do ma)19(nage t)21(o)-1( ag)19(ree on)19( )-20(mech)19(ani)5(sms )-20(to)19( )-20(share)]TJ
+0 -1.16 TD
+0.004 Tc
+0.078 Tw
+[(common )20(resou)20(r)-3(ces o)20(r)-3( pro)20(v)4(i)6(de pu)20(bl)6(i)6(c)4( goods. )20( )-20(Ostro)20(m)-3( )-20(\(1)20(990\) gi)6(ves )-20(an exampl)6(e)]TJ
+0 -1.14 TD
+0.258 Tw
+[(i)6(n)0( )20(S)11(outhern )20(C)26(a)0(l)6(i)6(f)2(orni)6(a )20(w)26(here )20(a com)17(m)-3(uni)6(ty a)20(g)0(ree)20(d)0( on a sys)24(tem t)22(o)0( man)20(age)]TJ
+0 -1.16 TD
+0.238 Tw
+[(groundw)6(a)20(t)2(er. A)11(f)2(t)22(e)0(r m)17(a)0(ki)6(ng the)20( agr)17(eeme)20(n)0(t, the c)24(o)0(mm)17(uni)6(ty )-20(app)20(eal)6(ed )-20(t)22(o)0( )-20(the)]TJ
+T*
+0.003 Tc
+0.499 Tw
+[(govern)19(m)-4(ent to)19( i)5(m)-4(pose)19( thi)5(s)3( as a )20(regul)25(ati)5(on, to)19( )-20(take )-20(a)19(d)-1(vanta)19(ge )-20(of )-20(t)21(h)-1(e)]TJ
+T*
+0.059 Tw
+[(govern)19(m)-4(ent\222)5(s)3( pow)25(ers to )20(enfo)19(r)-4(cemen)19(t, and)19( to bi)5(nd)19( actors)23( w)5(ho m)16(a)-1(y )-20(mi)5(gr)16(ate )-20(i)5(n)-1(to)]TJ
+T*
+0.004 Tc
+0.358 Tw
+[(the are)20(a)0( w)6(ho w)6(e)20(re not )20(party )20(to the )20(ori)6(g)0(i)6(nal)6( )20(agre)20(e)0(men)20(t. )-20(In )-20(so)20(me )-20(ot)22(her)]TJ
+0 -1.14 TD
+0.003 Tc
+-0.001 Tw
+[(exampl)5(es, t)21(he com)16(m)-4(uni)5(ty )20(desi)5(gns a)19(nd )-20(enf)21(orces )-20(t)21(he )-20(ag)19(reem)16(ent. )-20( For exampl)5(e)19( )-20(i)5(n)]TJ
+0 -1.16 TD
+0.179 Tw
+[(Mai)5(ne, l)5(o)-1(cal)5( c)23(o)-1(mm)16(uni)5(ti)5(es r)16(e)-1(stri)5(ct acce)19(ss to l)5(obst)21(e)-1(rs by )20(di)5(vi)5(di)5(ng th)19(e reso)19(urce)]TJ
+T*
+0.059 Tw
+[(among t)21(he com)16(m)-4(uni)5(ty )20(and en)19(forci)5(n)-1(g)19( thi)5(s)3( w)5(i)5(t)1(h l)5(o)-1(cal)5( c)23(o)-1(mm)16(uni)5(ty )-20(soci)5(al)5( )-20(p)19(r)-4(essur)16(e)-1(.)]TJ
+0 -1.5 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(23)Tj
+1.0952 -0.3095 TD
+1.444 Tw
+[( M)-8(y)-8(e)0(r)-8(s)-8(on-)-8(S)-8(a)0(t)-16(t)-16(e)0(r)15(t)-16(hwait)-16(e )1428(T)-16(heor)-8(em)]TJ
+ET
+endstream endobj 261 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 262 0 obj << /Type /Page /Parent 250 0 R /Resources 264 0 R /Contents 263 0 R >> endobj 263 0 obj << /Length 8619 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(55)Tj
+-34.32 58.98 TD
+0.003 Tc
+-0.001 Tw
+[(They a)19(r)-4(e, how)5(ev)23(er, occ)23(a)-1(si)5(onal)5(l)5(y)3( fo)19(rced t)21(o)-1( reso)19(rt to vi)25(ol)5(ence a)19(gai)5(nst pe)19(opl)5(e )-20(f)21(r)-4(om)]TJ
+0 -1.16 TD
+[(outsi)5(de the)19( comm)16(uni)5(ty, to)19( mai)5(n)-1(tai)25(n)-1( thei)5(r)16( l)5(o)-1(cal)5( cont)21(rol)5(.)]TJ
+0 -2.32 TD
+0.479 Tw
+[(Ostrom )20(al)5(s)23(o)-1( gi)5(ves nu)19(mer)16(ous exa)19(m)-4(pl)5(es w)5(h)-1(e)19(r)-4(e l)5(o)-1(cal)5( c)23(ontrol)5( )20(of com)16(m)-4(on)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(resourc)23(e)-1(s fai)5(l)5(s)3( beca)19(u)-1(se th)19(e com)16(m)-4(uni)5(ty i)5(s)3( to)19(o l)5(a)-1(rg)19(e, too )20(mobi)5(l)5(e)-1(, or )-20(si)5(mpl)5(y)3( fai)5(l)5(s)3( )-20(to)]TJ
+0 -1.16 TD
+0.339 Tw
+[(fi)5(nd an eff)21(e)-1(cti)5(v)3(e m)16(e)-1(chani)5(sm)16(. U)5(n)-1(for)16(t)1(unat)21(el)5(y thi)5(s)3( i)5(s)3( the )20(nor)16(m for v)23(a)-1(l)5(uabl)5(e)]TJ
+T*
+0.119 Tw
+[(common )40(resou)19(r)-4(ces )20(i)5(n)-1( )40(mode)19(rn )20(soci)5(ety.)21( P)10(r)-4(i)5(v)3(ate p)19(r)-4(ovi)5(s)3(i)5(on )20(of publ)5(i)5(c)3( )20(goods a)19(n)-1(d)]TJ
+T*
+-0.001 Tw
+[(protecti)5(on)19( of co)19(mmon )20(resou)19(r)-4(ces ge)19(neral)5(l)5(y)3( f)21(a)-1(i)5(l)5(s)3(.)]TJ
+0 -2.3 TD
+-0.001 Tc
+0.463 Tw
+[(An)-5(o)-5(t)-3(h)-5(e)-5(r)-8( e)-5(n)15(fo)-5(r)-8(c)-1(e)15(m)-8(e)-5(n)-5(t)-3( p)15(r)-8(o)-5(b)-5(l)1(e)15(m)-8( a)-5(r)-8(ise)-5(s)19( with)-5( lim)-8(ite)-5(d)-5( li)21(a)-5(b)-5(ility co)-5(m)-8(p)15(a)-5(n)-5(i)1(e)-5(s)-1( )-20(a)-5(n)15(d)]TJ
+0 -1.16 TD
+0.002 Tc
+0.18 Tw
+[(exter)-5(nalities )40(that involv)22(e r)-5(i)4(sks of )20(pollution )20(r)-5(a)-2(the)18(r)-5( tha)18(n)-2( actual )20(pollution. )20(If, fo)18(r)]TJ
+T*
+0.004 Tc
+0.138 Tw
+[(exampl)6(e, a)20( comp)20(any i)6(s)4( ma)20(nagi)6(ng )20(hazar)17(dous w)6(a)0(st)22(e, i)6(t)2( may)24( not )-20(c)24(r)-3(eate day )-20(to)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(day pol)5(l)5(u)-1(ti)5(on.)21( E)10(a)-1(ch day t)21(hey ri)5(sk )20(an acci)5(de)19(nt and s)23(houl)5(d )-20(t)21(a)-1(ke )-20(an effi)5(ci)5(ent )-20(l)5(e)-1(v)23(e)-1(l)]TJ
+T*
+0.079 Tw
+[(of preca)19(u)-1(ti)5(ona)19(ry meas)23(ures. )20( If )-20(how)5(ev)23(er )-20(a maj)5(o)-1(r acci)5(dent occurs, )-20(t)21(he )-20(co)19(mpany)]TJ
+0 -1.24 TD
+0.22 Tw
+[(will )20(go )20(bankr)-5(u)18(pt )20(and)18( )20(will )20(not )20(be f)20(o)-2(r)-5(c)2(ed)18( to be)18(ar)-5( all th)18(e costs th)18(ey im)-5(pos)22(e.)]TJ
+10.08 0 0 10.08 513.6 553.645 Tm
+-0.008 Tc
+(24)Tj
+12 0 0 12 99.36 536.72 Tm
+0.002 Tc
+0.02 Tw
+[(K)9(nowing this, com)15(panies will take)18( )-20(less )-20(than)18( )-20(efficient m)-5(easu)18(r)-5(es )-20(to pr)-5(eve)18(n)-2(t )-20(m)-5(a)-2(j)24(o)-2(r)]TJ
+0 -1.16 TD
+0.08 Tw
+[(problems)22( thoug)18(h they )20(may de)18(al efficiently wit)20(h small d)18(a)-2(y to day)22( risks. )-20( )-20(No)18(rmal)]TJ
+T*
+0.001 Tc
+0.001 Tw
+[(legal liability for)-6( )20(dam)-6(a)17(ges will lead t)19(o)-3( inefficient)19( outco)17(m)-6(e)-3(s. On)17(e way to )20(deal )-20(with)]TJ
+0 -1.14 TD
+0.004 Tc
+0.078 Tw
+[(thi)6(s)4( probl)6(e)20(m)-3(, i)6(s)4( to )20(requi)26(re a co)20(mpany )20(to pu)20(rchase i)26(n)0(suranc)24(e fro)20(m)-3( a )-20(t)22(h)0(i)6(r)-3(d )-20(pa)20(rty)]TJ
+0 -1.16 TD
+0.002 Tc
+0.28 Tw
+[(with the ability to)18( cover)-5( )20(the )-20(costs of )-20(the)18( )-20(lar)-5(gest accident)20(. )-20( )-20(T)-7(h)18(e )-20(insur)15(ance)]TJ
+T*
+-0.001 Tc
+0.123 Tw
+[(p)-5(r)-8(e)-5(m)-8(iu)15(m)-8( will r)-8(e)-5(fle)-5(c)-1(t t)17(h)-5(e)-5( le)-5(ve)-5(l o)-5(f)-3( )-20(ca)-5(r)-8(e)15( )-20(th)-5(e)-5( )-20(in)-5(s)19(u)-5(r)-8(a)-5(n)-5(c)-1(e)-5( co)-5(m)-8(p)15(a)-5(n)-5(y)-1( )-20(o)-5(b)-5(s)19(e)-5(r)-8(ve)-5(s. )-20( )-20( T)-10(h)-5(e)]TJ
+T*
+0.001 Tc
+0.041 Tw
+[(insur)-6(ance c)21(ontr)-6(a)-3(c)21(t)-1( will incr)-6(ease)17( the lev)21(e)-3(l of pr)-6(e)17(c)1(autio)17(n )-20(and )-20(will )-20(m)14(o)-3(ve )-20(som)14(e)-3( )-20(r)-6(i)3(sk)]TJ
+T*
+0 Tc
+0.042 Tw
+[(fr)-7(o)-4(m)-7( th)16(e)-4( p)-4(u)-4(b)-4(lic t)18(o)-4( th)-4(e)-4( in)-4(s)20(u)-4(r)-7(a)-4(n)-4(c)20(e)-4( co)-4(m)-7(p)16(a)-4(n)-4(y)0(; it will n)-4(o)-4(t)18( p)-4(e)-4(r)-7(f)18(e)-4(ctly so)-4(lve)-4( th)16(e)-4( p)-4(r)-7(o)16(b)-4(le)-4(m)]TJ
+0 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(because th)20(e mo)20(ral)6( haza)20(r)-3(d p)20(r)-3(obl)6(e)20(m)-3( re)20(mai)6(n)0(s.)]TJ
+0 -2.32 TD
+0.003 Tc
+0.219 Tw
+[(A)10( si)5(mi)5(l)5(a)-1(r probl)25(em a)19(r)-4(i)5(s)3(es beca)19(u)-1(se da)19(mages c)23(an be hard)19( )-20(to )-20(col)5(l)5(e)-1(ct ex )-20(post,)]TJ
+0 -1.16 TD
+0.004 Tc
+0.178 Tw
+[(parti)6(cul)6(a)0(rl)6(y )20(w)26(hen )20(th)20(ey )20(are)20( )20(l)6(a)0(rge)20(.)2( )20( A)11( comm)17(on exa)20(m)-3(pl)6(e of)22( thi)6(s)4( i)6(s)4( stri)6(p)20( mi)6(ni)6(ng,)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(which )20(causes unsi)25(ghtly da)19(mage )20(and r)16(unoff. )20( Mining c)23(o)-1(mpa)19(n)-1(ies ar)16(e req)19(u)-1(ired )20(to)]TJ
+0 -1.14 TD
+0.119 Tw
+[(restore)19( )20(the )20(l)5(a)-1(n)19(d)-1( )20(but )40(often )40(do )20(not )40(do )20(so )20(i)5(n)-1( )20(a sati)5(sfact)21(o)-1(ry o)19(r)-4( ti)5(mel)5(y)3( w)5(a)-1(y)23(.)1( S)10(o)-1(me)]TJ
+0 -1.16 TD
+0.099 Tw
+[(compani)5(es )40(di)5(ssol)5(v)3(e )20(aft)21(e)-1(r )20(th)19(e )20(mi)5(ne )20(i)5(s)3( )20(cl)25(osed, m)16(a)-1(ki)5(ng i)5(t)1( di)5(f)21(f)1(i)5(c)3(ul)5(t to p)19(uni)5(sh the)19(m)-4(.)]TJ
+T*
+0.119 Tw
+[(One sol)5(u)-1(ti)5(on )20(to thi)5(s)3( i)5(s)3( to)19( req)19(u)-1(i)5(r)-4(e th)19(e com)16(pany to post )-20(an)19( )-20(envi)5(r)-4(o)19(n)-1(men)19(t)1(al)5( )-20(bon)19(d)]TJ
+T*
+0.004 Tc
+[(equal)6( to t)22(he expec)24(ted cost)22( of res)24(t)2(orati)26(on. )20(The bo)20(nd )-20(w)6(oul)6(d be )-20(r)17(e)0(turn)20(ed )-20(w)6(hen)]TJ
+T*
+-0.002 Tw
+[(the comp)20(any can s)24(how)6( that)22( i)6(t)2( has ei)6(t)22(her av)24(oi)6(ded o)20(r)-3( mi)6(ti)6(g)20(a)0(ted a)20(n)0(y da)20(mage.)]TJ
+0 -2.3 TD
+0.018 Tw
+[(E)11(v)4(en )20(w)6(hen pr)17(operty)24( ri)6(ghts )20(are al)6(l)6(o)0(c)24(a)0(ted, )20(and re)20(l)6(a)0(ti)6(vel)6(y)4( sm)17(ooth n)20(egoti)6(a)0(ti)6(o)20(n)0( does)]TJ
+0 -1.16 TD
+0 Tc
+0.202 Tw
+[(o)-4(ccu)-4(r)-7(,)-2( th)-4(e)16( in)-4(itia)-4(l a)-4(llo)-4(ca)-4(tio)16(n)-4( o)-4(f)-2( p)16(r)-7(o)-4(p)-4(e)16(r)-7(t)-2(y r)-7(i)2(g)16(h)-4(ts )-20(still )-20(m)-7(a)-4(tt)18(e)-4(r)-7(s )-20(fo)16(r)-7( )-20(e)-4(fficie)16(n)-4(cy )-20(if )-20(th)-4(e)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(parti)5(es act)21(ual)5(l)5(y)3( neg)19(oti)5(a)-1(ti)5(ng d)19(o)-1( )-20(not rep)19(r)-4(esent al)5(l)5( )-20(the )-20(i)5(n)-1(te)19(rests. )-20( For)16( )-20(exam)16(pl)5(e,)]TJ
+T*
+0.004 Tc
+0.298 Tw
+[(w)6(hen )20(envi)6(r)-3(o)20(n)0(men)20(t)2(al)6( )20(gr)17(oups )20(a)20(r)-3(e ne)20(goti)6(a)0(ti)6(ng w)6(i)6(t)22(h oi)6(l)6( com)17(pani)6(es a)20(nd mi)6(ni)6(n)20(g)]TJ
+0 -1.14 TD
+0.002 Tc
+0.06 Tw
+[(inter)-5(e)-2(sts, b)18(e)-2(cause c)22(onser)-5(v)22(a)-2(tion is a )20(public goo)18(d, th)18(e envir)-5(o)18(n)-2(m)-5(e)-2(n)18(t)0(al )-20(gr)15(oups )-20(will)]TJ
+0 -1.16 TD
+[(tend to b)19(e)-1( i)5(neffi)5(ci)5(en)19(tl)5(y unde)19(r-r)16(esourc)23(ed. A)10(l)5(thou)19(gh so)19(me )-20(effi)5(ci)5(ency)23( )-20(gai)5(n )-20(ca)19(n )-20(be)]TJ
+T*
+-0.001 Tc
+0.203 Tw
+[(r)-8(e)-5(a)-5(lise)-5(d)-5(,)-3( th)-5(is)19( la)-5(ck o)-5(f)-3( r)12(e)-5(so)-5(u)-5(r)-8(c)19(e)-5(s will in)-5(e)-5(fficie)-5(n)-5(t)-3(ly b)-5(i)1(a)-5(s)-1( )-20(th)-5(e)-5( o)-5(u)-5(t)-3(co)-5(m)12(e)-5( )-20(a)-5(w)1(a)-5(y)-1( )-20(f)17(r)-8(o)-5(m)]TJ
+T*
+0.003 Tc
+[(conservati)5(o)19(n)-1(.)]TJ
+0 -2.3 TD
+0.219 Tw
+[(W)7(hen trans)23(acti)5(on costs)23( are )20(hi)5(gh, )-20(o)19(n)-1( )-20(effi)5(ci)5(ency grou)19(nds, )-20(gov)23(ernm)16(ent )-20(sh)19(oul)5(d)]TJ
+0 -1.16 TD
+0.139 Tw
+[(endeavou)19(r )20(to )40(al)5(l)5(o)-1(cate )20(p)19(r)-4(ope)19(rty )20(ri)5(g)19(h)-1(ts )20(to th)19(ose m)16(o)-1(st l)5(i)5(k)3(el)5(y to g)19(a)-1(i)5(n)-1( the )20(great)21(est)]TJ
+T*
+0.259 Tw
+[(val)5(ue to avoi)25(d seri)5(o)19(u)-1(s mi)5(sal)5(l)5(o)-1(cati)25(on. T)14(h)-1(i)5(s)3( )-20(pro)19(babl)5(y )-20(i)5(m)-4(pl)5(i)5(e)-1(s)23( )-20(that )-20(l)5(a)19(ndow)5(ne)19(rs)]TJ
+0 -1.5 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(24)Tj
+1.0952 -0.3095 TD
+1.444 Tw
+[( P)-8(olins)-8(k)-8(y)]TJ
+ET
+endstream endobj 264 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 265 0 obj << /Type /Page /Parent 250 0 R /Resources 267 0 R /Contents 266 0 R >> endobj 266 0 obj << /Length 7726 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(56)Tj
+-34.32 58.98 TD
+0.138 Tw
+[(shoul)6(d have)20( the sta)20(t)2(us qu)20(o pro)20(perty )20(ri)6(ghts )-20(t)22(o)0( )-20(al)6(ter pri)6(v)4(ate)20( )-20(l)6(and \(e.g.: )-20(t)22(h)0(rou)20(g)0(h)]TJ
+0 -1.16 TD
+0.003 Tc
+0.019 Tw
+[(subdi)5(vi)5(si)5(on or)16( bui)5(l)5(d)-1(i)5(n)-1(g)19(\))-4(. T)14(h)-1(i)5(s)3( i)5(s)3( )-20(consi)5(s)3(ten)19(t)1( )-20(w)5(i)5(t)1(h )-20(the part of )-20(the )-20(A)10(c)3(t, )-20(w)25(h)-1(i)5(c)3(h )-20(states)]TJ
+T*
+0.119 Tw
+[(that acti)5(vi)5(ti)5(es o)19(n)-1( pri)5(v)3(at)21(e l)5(and )20(are p)19(e)-1(rmi)5(tt)21(ed unl)5(ess)23( the pl)25(an )-20(exp)19(r)-4(essl)5(y )-20(rest)21(ri)5(cts)]TJ
+T*
+0.239 Tw
+[(them. H)5(o)-1(w)5(e)-1(v)23(e)-1(r i)5(t)1( )20(may be i)5(n)19( confl)5(i)5(c)3(t w)5(i)5(t)1(h )-20(t)21(he )-20(ri)5(g)19(h)-1(t )-20(of )-20(a)19(n)-1(y )-20(ci)5(ti)5(zen )-20(to)19( )-20(make)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(submi)5(ssi)5(ons o)19(n)-1( and )20(appeal)5( c)23(onsent )20(deci)5(s)3(i)5(ons.)]TJ
+0 -2.32 TD
+0.219 Tw
+[(If one g)19(r)-4(oup f)21(a)-1(ces hi)5(gh)19(er t)21(r)-4(ansacti)5(o)19(n)-1( costs of)21( i)5(n)-1(i)5(t)1(i)5(a)-1(ti)5(ng n)19(egoti)5(a)-1(ti)25(on )-20(tha)19(n)-1( )-20(the)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(other, o)20(t)2(her )20(thi)6(ngs e)20(qual)6(, i)6(t)2( i)6(s)4( b)20(e)0(tter )20(to al)6(l)6(o)0(cate)20( the )20(ri)6(ghts t)22(o)0( )-20(the )-20(g)20(r)-3(oup)20( )-20(w)6(i)6(t)2(h )-20(hi)6(gh)]TJ
+T*
+0 Tc
+0.062 Tw
+[(tr)-7(a)-4(n)-4(s)0(a)-4(c)0(tio)-4(n)16( )20(co)-4(sts. )20( )20(Ne)16(g)-4(o)-4(t)-2(ia)-4(tio)-4(n)-4( )20(will th)16(e)-4(n)-4( b)-4(e)16( m)-7(o)-4(r)13(e)-4( like)-4(l)2(y to)-4( o)-4(c)0(c)20(u)-4(r)-7( if )20(r)-7(e)-4(so)-4(u)-4(r)-7(c)20(e)-4(s a)-4(r)13(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.298 Tw
+[(mi)6(sal)6(l)6(o)0(cated. )20( In N)6(e)0(w)6( Z)15(eal)6(and)20(, w)6(here)20( )-20(non)20(-gove)20(r)-3(nme)20(n)0(tal)6( )-20(or)17(gani)6(sati)6(o)20(n)0(s )-20(are)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(poorl)5(y)3( dev)23(el)5(oped )20(and fu)19(nded, )20(they a)19(r)-4(e fi)5(ndi)5(n)19(g)-1( the c)23(o)-1(sts of f)21(u)-1(l)5(l)5( parti)5(ci)5(p)19(a)-1(ti)5(on )-20(i)5(n)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(the R)6(M)-3(A)11( proc)24(ess pro)20(h)0(i)6(b)0(i)6(t)2(i)6(v)4(e. Tanga)20(ta )-20(w)6(hen)20(ua )-20(ar)17(e )-20(al)6(so )-20(fi)6(n)20(d)0(i)6(ng )-20(pa)20(rti)6(c)4(i)6(pati)6(o)20(n)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(costl)5(y)3(. Larg)19(e)-1( busi)5(n)19(esses may)23( be abl)25(e to p)19(r)-4(ovi)5(de i)5(n)-1(f)21(o)-1(rm)16(ati)5(on an)19(d )-20(set )-20(u)19(p)]TJ
+T*
+0.219 Tw
+[(processes t)21(o)-1( neg)19(oti)5(a)-1(te th)19(ei)5(r bi)5(d )20(or cl)5(ai)5(m)16( for )20(resou)19(r)-4(ces m)16(o)-1(re ef)21(fi)5(ci)5(entl)5(y)3( tha)19(n)]TJ
+0 -1.14 TD
+0.319 Tw
+[(communi)5(ty )40(grou)19(ps. )20( T)14(h)-1(i)5(s)3( i)5(s)3( consi)5(s)3(ten)19(t)1( w)5(i)5(t)1(h the A)10(c)3(t\222)5(s p)19(r)-4(ovi)5(s)3(i)5(on t)21(hat pu)19(bl)5(i)5(c)]TJ
+0 -1.16 TD
+0.059 Tw
+[(resourc)23(e)-1(s )20(canno)19(t )20(be )20(us)23(ed )20(by p)19(r)-4(i)5(v)3(ate a)19(c)3(tors un)19(l)5(e)-1(ss i)5(t)1( i)5(s)3( speci)5(f)1(i)5(c)23(al)5(l)5(y)3( al)5(l)5(o)-1(w)5(ed; th)19(e)]TJ
+T*
+0.239 Tw
+[(communi)5(ty )20(has the)19( status )20(quo p)19(r)-4(ope)19(rty ri)5(gh)19(ts, )-20(not potenti)5(a)-1(l)5( users of )-20(publ)5(i)5(c)]TJ
+T*
+[(resourc)23(e)-1(s.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.538 Tw
+[(Fi)6(nal)6(l)6(y)4(, som)17(e)0( gro)20(ups ar)17(e una)20(bl)6(e to )20(repr)17(esent )-20(th)20(emsel)6(v)4(es,)22( )-20(e.g.: )-20(f)22(u)0(tur)17(e)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(generati)25(ons. )20( Gov)23(e)-1(rn)19(ment so)19(meti)5(mes)23( needs)23( to act )20(as thei)5(r)16( agents)23( to p)19(r)-4(otect)]TJ
+T*
+0.219 Tw
+[(thei)5(r )20(i)5(n)-1(te)19(rests w)5(h)-1(e)19(n)-1( i)5(n)-1(ter)16(gene)19(rati)5(onal)5( )20(al)5(trui)5(sm)16( i)5(s)3( i)5(n)-1(suffi)5(ci)5(ent)21( and cu)19(rre)19(nt and)]TJ
+T*
+0.004 Tc
+-0.022 Tw
+[(future )-20(i)6(n)0(t)22(e)0(rests are mi)6(sal)6(i)6(gned)20(.)]TJ
+0 -2.3 TD
+0.138 Tw
+[(A)11(l)6(l)6(o)0(cati)6(on and e)20(n)0(force)20(m)-3(ent )20(of pr)17(operty)24( ri)6(ghts, a)20(nd l)6(i)6(m)-3(i)6(t)22(ed re)20(gul)6(ati)6(on )20(\(such as)]TJ
+0 -1.16 TD
+0.003 Tc
+0.259 Tw
+[(tradeabl)25(e per)16(mi)5(t ma)19(rkets o)19(r)-4( envi)25(r)-4(onm)16(ental)5( bon)19(ds\) are )-20(su)19(ffi)5(ci)5(ent )-20(to addr)16(ess)]TJ
+T*
+0.039 Tw
+[(some res)23(ource)19( i)5(ssues, bu)19(t i)5(n)-1( oth)19(e)-1(r si)5(tua)19(t)1(i)5(ons, di)25(rect )-20(gov)23(ernm)16(ent )-20(r)16(egul)5(ati)5(o)19(n )-20(and)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(provi)6(s)4(i)6(on a)20(r)-3(e ne)20(eded.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 343.52 Tm
+0.008 Tc
+-0.026 Tw
+[(I)6(n)-1(for)17(m)17(a)4(ti)26(on Fai)6(l)6(u)-1(r)17(e)4(s)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 317.36 Tm
+0.003 Tc
+0.279 Tw
+[(R)5(e)-1(sources, )40(and )20(esp)19(e)-1(ci)5(al)5(l)5(y)3( envi)5(r)16(onmen)19(tal)5( res)23(ources,)21( such as cl)5(e)19(an ai)5(r)16(,)1( are)]TJ
+T*
+0.079 Tw
+[(often un)19(usual)5( co)19(mmodi)5(ti)5(es)23(. Many)23( )-20(of )-20(th)19(ei)5(r )-20(char)16(acte)19(ri)5(sti)5(cs )-20(are unobse)19(r)-4(vabl)5(e by)]TJ
+0 -1.14 TD
+0.099 Tw
+[(those )20(w)5(ho )20(co)19(nsume)19( )20(them)16(. )20( Fo)19(r exa)19(m)-4(pl)5(e, m)16(any pol)5(l)5(u)19(tants a)19(r)-4(e un)19(detecta)19(bl)5(e by)]TJ
+0 -1.16 TD
+0.279 Tw
+[(human se)19(nses eve)19(n)-1( i)5(f)1( they )20(are c)23(ausi)5(ng h)19(a)-1(rm. )20( )-20(In )-20(a)19(ddi)5(ti)5(on, many )-20(of)21( )-20(the)]TJ
+T*
+0.199 Tw
+[(resourc)23(e)-1( i)5(ssues w)5(e)-1( d)19(eal)5( w)5(i)5(t)1(h to)19(day ar)16(e rel)5(a)19(ti)5(vel)5(y)3( new)5( i)5(ssues)23( so peo)19(pl)5(e )-20(ar)16(e)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(unaccustom)17(ed to )20(them. )20( The)20( possi)6(bl)6(e )20(dange)20(rs fro)20(m)-3( cel)6(l)6( ph)20(one us)24(e and )-20(t)22(o)0(w)6(e)0(rs)]TJ
+T*
+0.003 Tc
+0.039 Tw
+[(are onl)5(y n)19(o)-1(w)5( beco)19(m)-4(i)5(ng a)19(n)-1( i)5(ssue. )20(Many )-20(p)19(o)-1(l)5(l)5(u)-1(tants )-20(a)19(r)-4(e )-20(o)19(n)-1(l)5(y)3( )-20(dang)19(erous above a)]TJ
+0 -1.14 TD
+0.004 Tc
+0.118 Tw
+[(threshol)6(d )20(that i)6(s)4( o)20(n)0(l)6(y)4( bei)6(ng )20(passed )20(now)6( becau)20(se of )20(popul)6(ati)6(o)20(n )-20(and)20( )-20(econo)20(mi)6(c)]TJ
+0 -1.16 TD
+0.003 Tc
+0.199 Tw
+[(grow)5(th. )20(Many co)19(mmon)19( reso)19(urces o)19(n)-1(l)5(y)3( beco)19(m)-4(e )-20(scar)16(c)3(e )-20(w)5(i)5(t)1(h )-20(con)19(gesti)5(on and)]TJ
+T*
+0.079 Tw
+[(heavy dem)16(and. S)10(o)19(me pr)16(obl)5(ems )20(are )20(ol)5(d, )-20(but )-20(o)19(n)-1(l)5(y)3( )-20(now)5( recogni)5(s)23(ed, )-20(o)19(r)-4( )-20(conce)19(r)-4(n)]TJ
+T*
+0.059 Tw
+[(has )20(ri)5(sen w)5(i)5(t)1(h)19( hi)5(ghe)19(r i)5(n)-1(com)16(e)-1( l)5(e)-1(vel)5(s)3(. N)5(e)-1(w)5(n)19(ess mea)19(n)-1(s that)21( i)5(ndi)5(vi)5(dual)5(s h)19(a)-1(ve no)19(t)]TJ
+T*
+0.004 Tc
+0.218 Tw
+[(devel)6(oped )40(experi)26(ence, a)20(nd i)6(n)0(sti)6(t)2(uti)6(o)20(ns to di)6(sse)20(mi)6(nat)22(e i)6(n)0(for)17(m)-3(ati)6(on )20(are )20(poorl)6(y)]TJ
+0 -1.14 TD
+[(devel)6(oped.)]TJ
+0 -2.32 TD
+0.002 Tc
+0.14 Tw
+[(B)9(e)-2(cause of th)18(e newness )20(of the iss)22(ues, an)18(d the lack)22( of obs)22(er)-5(vability, and )-20(th)18(e)]TJ
+0 -1.16 TD
+0.519 Tw
+[(physi)5(cal)5( natu)19(r)-4(e of )20(resou)19(r)-4(ces, un)19(derst)21(andi)5(ng th)19(ei)5(r e)19(ffects )-20(oft)21(en )-20(r)16(equi)5(res)]TJ
+T*
+0.019 Tw
+[(speci)5(a)-1(l)5(i)5(s)3(ed sci)5(enti)5(f)1(i)5(c)3( kn)19(ow)5(l)5(edge )20(and u)19(nderst)21(andi)5(ng.)21( Th)19(e i)5(nher)16(ent co)19(mpl)5(e)-1(xi)5(ty )-20(of)]TJ
+ET
+endstream endobj 267 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 268 0 obj << /Type /Page /Parent 250 0 R /Resources 270 0 R /Contents 269 0 R >> endobj 269 0 obj << /Length 7085 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(57)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.019 Tw
+[(the i)5(ssues i)5(s)3( exac)23(erba)19(ted bec)23(ause many )-20(envi)5(r)16(onm)16(ental)5( )-20(e)19(ffects )-20(a)19(r)-4(e )-20(on heal)5(th of)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(humans o)19(r)-4( ecosyst)21(ems a)19(nd involve )20(risk rat)21(her t)21(han ce)19(rtain ef)21(fects. )-20( )-20(If)21( )-20(a )-20(pollut)21(ant)]TJ
+T*
+0.179 Tw
+[(onl)5(y har)16(ms one )20(perso)19(n i)5(n)-1( a th)19(ousand)19( i)5(t)1( i)5(s)3( )-20(di)5(ffi)5(cul)5(t)1( )-20(t)21(o)-1( )-20(obse)19(r)-4(ve )-20(i)5(t)1(s )-20(eff)21(e)-1(ct, )-20(an)19(d)]TJ
+T*
+0.219 Tw
+[(di)5(ffi)5(cul)5(t)1( for a)19(n)-1( i)5(ndi)5(vi)5(du)19(al)5( to deci)5(d)19(e the )20(appr)16(opri)5(a)-1(t)21(e)-1( l)5(e)-1(vel)5( of )20(protec)23(ti)5(ve acti)5(on.)]TJ
+0 -1.14 TD
+0.039 Tw
+[(Many )20(effec)23(t)1(s onl)5(y occ)23(u)-1(r ove)19(r)-4( l)5(ong )20(peri)5(o)19(ds of ti)5(m)16(e)-1( so by t)21(he ti)5(m)16(e)-1( the e)19(ffects a)19(r)-4(e)]TJ
+0 -1.16 TD
+0.079 Tw
+[(observed i)5(t)21( i)5(s)3( too l)5(a)-1(t)21(e)-1( to p)19(r)-4(event)21( futur)16(e)-1( effec)23(t)1(s, )-20(and al)5(so )-20(di)5(ffi)5(cul)5(t)1( to )-20(i)5(denti)5(f)1(y)23( )-20(the)]TJ
+T*
+0.019 Tw
+[(true )20(caus)23(es of th)19(e effects)23(.)1( Th)19(e unce)19(r)-4(tai)5(n)-1(ty )20(and th)19(e ti)5(me fr)16(am)16(e pro)19(b)-1(l)5(e)-1(ms pl)5(a)19(gue)]TJ
+T*
+0.16 Tw
+[(epidem)-5(iologic)22(a)-2(l )20(studies )40(and )20(un)18(der)-5(st)20(anding )40(of ecolo)18(g)-2(ical stability, a)18(nd m)-5(a)-2(k)22(e)-2( it)]TJ
+T*
+-0.001 Tw
+[(i)5(m)-4(possi)5(bl)5(e fo)19(r any i)5(n)19(di)5(vi)5(dual)5( to l)25(earn f)21(r)-4(om)16( experi)25(ence a)19(nd obse)19(r)-4(vati)5(on)19(.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.238 Tw
+[(These )20(ac)24(ute )20(i)6(n)0(fo)20(rmati)26(on pr)17(obl)6(ems c)24(r)-3(eate)20( a pot)22(enti)6(a)0(l)6( r)17(o)0(l)6(e)0( for)17( gove)20(r)-3(nmen)20(t i)6(n)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(i)5(n)-1(formati)25(on col)5(l)5(e)-1(cti)5(o)-1(n)19( and )20(di)5(ssemi)5(nati)25(on, an)19(d possi)5(bl)5(y i)5(n)-1( s)23(e)-1(tti)5(ng b)19(a)-1(si)5(c )-20(stand)19(ards)]TJ
+T*
+0.359 Tw
+[(of protec)23(ti)5(on. I)21(ndi)5(vi)5(dual)5(s n)19(eed i)5(n)-1(fo)19(rma)19(ti)5(on to )-20(ta)19(ke )-20(effi)5(ci)5(e)19(n)-1(t )-20(pr)16(ecauti)5(o)-1(n)19(a)-1(ry)]TJ
+T*
+0.239 Tw
+[(measur)16(es )20(and )20(t)21(o)-1( neg)19(oti)5(a)-1(te e)19(ffecti)5(v)3(el)5(y w)5(i)5(t)1(h p)19(o)-1(l)5(l)5(u)-1(ters )20(of vi)5(cti)5(m)-4(s. R)25(egul)5(ato)19(r)-4(s,)]TJ
+0 -1.14 TD
+0.004 Tc
+0.218 Tw
+[(w)6(hether l)6(o)0(c)24(a)0(l)6( or ce)20(ntral)6(,)2( )20(al)6(so nee)20(d thi)6(s)4( i)6(n)0(f)22(o)0(rma)20(ti)6(on to )20(make )-20(a)20(nd )-20(i)6(m)-3(pl)26(ement)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(regul)5(ati)5(ons)23( effecti)5(v)3(el)5(y.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 510.08 Tm
+0.004 Tc
+-0.002 Tw
+[(W)8(h)-5(at is )20(th)-5(e r)13(o)15(le o)15(f)-3( t)17(h)-5(e RMA)26(?)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 483.92 Tm
+0.003 Tc
+0.119 Tw
+[(The )20(R)5(M)-4(A)10( )20(has)23( a br)16(oad m)16(andat)21(e across)23( types of)21( reso)19(urces. )20(For)16( w)5(h)-1(i)5(c)3(h i)5(ssues)]TJ
+T*
+0.399 Tw
+[(are the )20(fai)5(l)5(u)-1(res )20(of pri)5(v)23(ate sol)5(u)-1(ti)5(o)19(n)-1(s to ex)23(ternal)5(i)5(t)1(i)5(e)-1(s)23( suffi)5(ci)5(entl)5(y)3( )20(great)21( )-20(that)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(govern)20(m)-3(ent )40(regul)6(ati)6(o)20(n )20(i)6(s)4( )20(nee)20(ded? W)8(h)20(ere can)20( gove)20(r)-3(nm)17(ent re)20(gul)6(ati)6(o)0(n)20( be l)6(i)6(m)-3(i)6(t)2(e)20(d)]TJ
+T*
+0 Tc
+0.462 Tw
+[(to)-4( th)-4(e)-4( d)-4(e)16(fin)-4(i)2(tio)-4(n)-4( a)-4(n)16(d)-4( )-20(e)-4(n)-4(f)-2(o)16(r)-7(ce)-4(m)13(e)-4(n)-4(t)-2( )-20(o)-4(f)-2( p)-4(r)-7(o)-4(p)16(e)-4(r)-7(ty r)-7(i)2(g)-4(h)-4(t)-2(s )-20(to)-4( fa)-4(cilita)-4(t)-2(e)-4( )-20(p)16(r)-7(iva)-4(t)-2(e)]TJ
+0 -1.14 TD
+0.003 Tc
+0.679 Tw
+[(sol)5(u)-1(ti)5(ons? )20(Theo)19(ry sugge)19(sts gove)19(r)-4(nme)19(n)-1(t shoul)25(d focus )20(on )-20(re)19(gul)5(ati)5(n)-1(g)]TJ
+0 -1.16 TD
+0.559 Tw
+[(external)5(i)5(t)1(i)5(e)-1(s )20(that af)21(fect pu)19(bl)5(i)5(c)3( )-20(goods and )-20(co)19(mmon)19( )-20(pro)19(perty resou)19(r)-4(ces,)]TJ
+T*
+0.12 Tw
+[(particularly )40(those )20(t)20(hat )20(involve)18( )20(high o)18(ngoing c)22(o)-2(sts, high)18( risks or)15( large)18( one ti)24(me)]TJ
+T*
+0.004 Tc
+(damages.)Tj
+0 -2.3 TD
+0.002 Tc
+0.3 Tw
+[(Regulation )20(of)20( )20(non)18(-)-5(public )20(ext)20(e)-2(r)-5(nalities )20(c)22(ould be li)24(m)-5(i)4(ted t)20(o)-2( a facilitati)24(on r)-5(o)-2(le)18(.)]TJ
+0 -1.16 TD
+0.12 Tw
+[(Local )20(gove)18(r)-5(nm)-5(e)18(n)-2(t )20(should)18( )20(be a)18(b)-2(le to facilita)18(t)0(e ag)18(r)-5(eem)15(ents on)18( exter)15(nalities tha)18(t)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(affect very s)24(m)-3(al)6(l)6( nu)20(mbers)24( of pe)20(opl)6(e. )20(Thei)6(r rol)6(e)0( )-20(sh)20(oul)6(d )-20(be )-20(l)6(i)26(mi)6(ted )-20(to)20( )-20(medi)6(a)20(t)2(i)6(on,)]TJ
+T*
+0.058 Tw
+[(and reco)20(rdi)6(ng )20(and e)20(n)0(forci)6(n)20(g agr)17(eeme)20(n)0(ts am)17(ong aff)22(e)0(cted )20(parti)6(es.)22( )-20(W)8(here ther)17(e)]TJ
+T*
+0.438 Tw
+[(are ma)20(ny si)6(mi)6(l)6(a)0(r si)6(t)22(uati)6(ons,)22( e.g.: )20(mi)6(nor )20(house al)26(terati)26(ons, du)20(pl)6(i)6(c)4(ati)6(on )-20(of)]TJ
+0 -1.14 TD
+0.003 Tc
+0.179 Tw
+[(negoti)5(a)-1(ti)5(ons)23( may b)19(e)-1( avoi)5(de)19(d by havi)25(ng )-20(rul)25(e)-1(s )-20(of )-20(th)19(umb )-20(f)21(o)-1(r )-20(acti)5(vi)5(ti)5(es that )-20(a)19(r)-4(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(al)6(l)6(o)0(w)6(ed )20(w)6(i)6(t)2(hout t)22(he ag)20(ree)20(m)-3(ent of)22( othe)20(r affecte)20(d)0( pa)20(rti)6(e)0(s. E)11(l)6(sew)6(h)0(e)20(r)-3(e they)24( can)]TJ
+T*
+0.002 Tc
+0.48 Tw
+[(r)-5(educe )20(t)20(r)-5(ansacti)24(on costs )20(by cer)-5(t)0(ifyin)18(g)-2( the c)22(r)-5(edibility of)20( infor)15(m)-5(ation, )20(and)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(provi)6(d)0(i)6(ng a)20( foru)20(m fo)20(r di)6(scussi)6(on.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.279 Tw
+[(In terms)23( of i)5(n)-1(fo)19(rmati)5(o)19(n)-1(, the)19( gover)16(nmen)19(t shoul)5(d )20(focus o)19(n)-1( i)5(denti)5(f)1(yi)5(n)19(g)-1( cri)5(t)1(i)5(c)3(al)]TJ
+0 -1.16 TD
+0.004 Tc
+0.138 Tw
+[(i)6(n)0(formati)26(on pr)17(obl)6(ems. )20( Thes)24(e coul)6(d )20(be si)6(tuati)26(ons )-20(w)6(h)0(e)20(r)-3(e )-20(the potenti)26(a)0(l)6( )-20(har)17(m )-20(i)6(s)]TJ
+T*
+-0.002 Tw
+[(great, cos)24(t)2(s of av)24(oi)6(dance )20(are l)6(o)0(w)6( )20(rel)6(a)0(ti)6(ve t)22(o)0( the harm)17(,)2( )-20(and )-20(i)6(n)20(di)6(vi)6(dual)6( )-20(i)6(n)0(f)22(o)0(rma)20(ti)6(on)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(i)5(s)3( poor. In)19( ter)16(m)-4(s of d)19(e)-1(vol)5(u)-1(ti)5(on, the )-20(qu)19(esti)5(on )-20(i)5(s)3( )-20(w)5(h)19(at )-20(l)5(e)-1(vel)5( )-20(of gover)16(nmen)19(t )-20(most)]TJ
+T*
+-0.001 Tw
+[(effecti)5(v)3(el)5(y col)5(l)5(e)-1(cts, )20(anal)5(yses a)19(nd di)5(sse)19(mi)5(nates )20(data a)19(nd sets st)21(anda)19(rds.)]TJ
+ET
+endstream endobj 270 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 271 0 obj << /Length 7744 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(58)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.006 Tc
+-0.004 Tw
+[(A)8(ppen)17(d)-3(ix )20(Thr)15(ee)22(: T)17(h)-3(e Ti)24(eb)17(out )20(Mo)17(del )20(of M)19(obi)24(lity )20(and)17( P)13(r)15(efer)15(ence R)8(e)22(velat)19(ion)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.038 Tw
+[(The )20(p)20(r)-3(efer)17(ence )20(r)17(e)0(vel)6(a)0(ti)6(on)20( probl)26(ems ul)6(ti)26(matel)6(y)4( a)20(r)-3(i)6(s)4(e beca)20(u)0(se the)20(r)-3(e i)6(s)4( n)20(o)0( ma)20(rket)]TJ
+0 -1.14 TD
+-0.002 Tw
+[(for publ)6(i)6(c)4( g)20(oods. )20(Thi)6(s)4( p)20(r)-3(obl)6(em)17( i)6(s)4( unavoi)6(d)20(abl)6(e at )20(a cent)22(ral)6( gove)20(r)-3(nm)17(ent l)6(e)0(vel)6(,)2( but,)]TJ
+0 -1.16 TD
+0.258 Tw
+[(w)6(i)6(t)2(h )20(a )20(mobi)6(l)6(e)0( )40(popul)6(ati)26(on, can )20(be a)20(r)-3(gued )20(to be l)6(e)0(ss)24( of a )20(probl)6(e)20(m)-3( fo)20(r l)6(o)0(cal)]TJ
+T*
+0 Tc
+0.582 Tw
+[(g)-4(o)-4(v)0(e)-4(r)-7(n)16(m)-7(e)-4(n)-4(t. I)18(f)-2( m)-7(o)-4(b)-4(ility is sig)16(n)-4(ifica)-4(n)-4(t, lo)-4(c)20(a)-4(l g)-4(o)-4(v)0(e)16(r)-7(n)-4(m)-7(e)16(n)-4(ts )-20(ca)-4(n)-4( )-20(a)-4(c)20(t )-20(a)-4(s)]TJ
+T*
+0.003 Tc
+0.239 Tw
+[(entrep)19(r)-4(eneu)19(rs )20(tha)19(t)1( )20(offe)19(r )20(di)5(ffe)19(rent )20(p)19(a)-1(ckages )40(of l)5(o)-1(cal)5( pu)19(bl)5(i)5(c)3( goods)23( and t)21(a)-1(xes.)]TJ
+T*
+0.459 Tw
+[(B)10(e)-1(cause of i)5(n)-1(te)19(rj)5(uri)5(s)3(di)5(cti)5(o)19(nal)5( com)16(peti)5(t)1(i)5(on, j)25(u)-1(ri)5(sdi)5(c)3(ti)5(ons )20(have i)5(n)-1(c)23(enti)5(v)3(es )-20(to)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(provi)6(de th)20(e publ)6(i)6(c)4( )20(good )20(mi)6(x )-20(that agents, and )-20(pa)20(rti)6(c)4(ul)6(a)20(r)-3(l)6(y)4( )-20(mobi)6(l)6(e)0( agents)24(,)2( )-20(w)6(ant.)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(These )20(e)19(n)-1(trep)19(rene)19(urs )20(al)5(so)19( )20(have )20(i)5(n)-1(c)23(enti)5(v)3(es to p)19(r)-4(ovi)5(d)19(e the l)5(o)-1(c)23(a)-1(l)5( publ)5(i)5(c)3( g)19(oods i)5(n)]TJ
+T*
+0.219 Tw
+[(an )20(effi)5(ci)5(ent )20(w)5(a)-1(y)23(.)1( )20(Thi)5(s)3( l)5(e)19(ads to )20(a stro)19(ng ar)16(gume)19(n)-1(t for)16( devol)5(uti)5(o)19(n of d)19(e)-1(ci)5(si)5(on)]TJ
+T*
+-0.001 Tw
+[(maki)5(ng on )20(publ)5(i)5(c)3( go)19(ods.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.078 Tw
+[(The Ti)26(ebout model)6( \(Ti)6(e)0(b)20(out, )-20(1)20(956\) )-20(i)6(s)4( based on )-20(a )-20(co)20(mpeti)6(t)2(i)6(v)4(e mark)24(et )-20(anal)26(ogy.)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(E)10(n)-1(trepren)19(eurs )20(c)23(r)-4(eate)19( comm)16(uni)5(ti)5(es, p)19(r)-4(ovi)5(de l)5(o)-1(c)23(a)-1(l)5( publ)5(i)5(c)3( g)19(oods a)19(nd cha)19(r)-4(ge a)19(n)]TJ
+T*
+0.099 Tw
+[(access cost. B)10(oun)19(dari)5(e)-1(s of )-20(com)16(m)-4(uni)5(ti)5(es are )-20(e)19(ndoge)19(nous. )-20(I)21(ndi)5(vi)5(dual)5(s )-20(ch)19(oose)]TJ
+T*
+0.019 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(ons / co)19(mmu)19(ni)5(ti)5(es base)19(d)-1( on t)21(he l)5(e)-1(vel)5( of)21( l)5(o)-1(cal)5( publ)5(i)5(c)3( goods )-20(t)21(hey )-20(pr)16(ovi)5(d)-1(e)]TJ
+T*
+0.159 Tw
+[(and the )20(access cost. P)10(e)19(opl)5(e r)16(e)-1(veal)5( thei)25(r pr)16(efere)19(n)-1(ces w)5(i)5(t)1(h th)19(ei)5(r fe)19(et. U)5(nde)19(r)]TJ
+0 -1.14 TD
+0.04 Tw
+[(str)-5(i)4(ct )20(conditio)18(n)-2(s, outline)18(d)-2( below, )20(each individ)18(ual will end u)18(p)-2( in a c)22(o)-2(m)-5(m)-5(u)18(nity that)]TJ
+0 -1.16 TD
+0.099 Tw
+[(produces )20(exactl)5(y th)19(e l)5(e)-1(vel)5( of )20(publ)5(i)5(c)3( go)19(ods she )20(desi)5(r)-4(es. A)10(l)5(l)5( i)5(ndi)5(vi)5(d)19(ual)5(s )-20(w)5(i)5(t)1(hi)5(n )-20(a)]TJ
+T*
+0.001 Tc
+0.121 Tw
+[(com)-6(m)-6(unity will b)17(e)-3( identical.)19( Com)-6(p)-3(e)17(t)-1(ition a)17(m)-6(ong c)21(o)-3(m)-6(m)-6(u)17(nities )-20(will )-20(ensu)17(r)-6(e )-20(that)]TJ
+T*
+0.002 Tc
+0.24 Tw
+[(each com)15(m)-5(unity will be t)20(he size t)20(hat )-20(p)18(r)-5(oduces the )-20(pu)18(blic )-20(goods efficiently.)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(Thus )20(the)20( )20(pref)22(erenc)24(e )20(revel)26(a)0(ti)6(on p)20(r)-3(obl)6(e)20(m)-3( and th)20(e effi)6(ci)6(e)20(n)0(t pr)17(ovi)6(s)4(i)6(on pr)17(obl)6(em )20(are)]TJ
+0 -1.14 TD
+0.003 Tc
+0.519 Tw
+[(sol)5(v)3(ed. )20( )20(P)10(ubl)5(i)5(c)3( )20(goo)19(ds )20(are)19( pro)19(duced e)19(ffi)5(ci)5(entl)5(y)3(. I)21(n)-1( thi)5(s)3( w)5(o)-1(rl)25(d, cent)21(ral)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.203 Tw
+[(g)-5(o)-5(v)-1(e)-5(r)-8(n)15(m)-8(e)-5(n)-5(t)-3(\222s r)12(o)-5(le)-5( wo)-5(u)-5(l)1(d)-5( )20(b)-5(e)-5( lim)-8(ite)-5(d)15( to)-5( g)-5(i)1(vin)-5(g)-5( l)21(o)-5(ca)-5(l co)-5(m)12(m)-8(u)-5(n)-5(i)1(tie)-5(s)-1( t)17(h)-5(e)-5( a)-5(b)-5(ility t)17(o)]TJ
+T*
+0.004 Tc
+0.678 Tw
+[(demand )20(payme)20(nt fo)20(r servi)6(c)4(es w)6(i)6(t)22(hi)6(n )-20(com)17(m)-3(uni)6(ti)6(es, and )-20(h)20(e)0(l)6(p)0(i)6(ng )-20(l)6(o)0(cal)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(communi)5(ti)5(es)23( enfo)19(r)-4(ce such s)23(e)-1(rvi)5(c)3(e co)19(ntracts)23(.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.038 Tw
+[(The Ti)26(ebout )20(model)6( i)6(s)4( )20(a theo)20(reti)6(cal)6( co)20(nstructi)6(on)20( not )20(a mode)20(l)6( of r)17(eal)6(i)6(t)2(y. Its )-20(v)24(a)0(l)6(u)0(e)]TJ
+0 -1.16 TD
+0.003 Tc
+[(i)5(n)-1( provi)5(d)-1(i)5(ng i)25(n)-1(si)5(ght i)5(n)-1(t)21(o)-1( the b)19(enefi)5(t)1(s o)19(f)1( devol)5(u)19(t)1(i)5(on de)19(pends p)19(a)-1(rtl)5(y)3( o)19(n)-1( )-20(w)5(hethe)19(r )-20(i)5(t)1(s)]TJ
+0 -1.26 TD
+0.199 Tw
+[(assumpti)5(ons)23( )20(have a)19(n)-1(y rel)5(a)19(ti)5(onshi)5(p w)5(i)5(t)1(h )20(real)5(i)5(t)1(y.)]TJ
+10.08 0 0 10.08 358.56 333.085 Tm
+-0.008 Tc
+(25)Tj
+12 0 0 12 369.6 330.08 Tm
+0.004 Tc
+0.198 Tw
+[( R)6(ubi)6(nfel)6(d s)24(u)0(mm)17(ari)6(s)4(es th)20(e)]TJ
+-22.52 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(Ti)5(ebout )20(assumpti)25(ons as f)21(o)-1(l)5(l)5(o)-1(w)5(s)3(:)]TJ
+0 -2.3 TD
+[(1.)-1519(Indi)5(vi)5(dual)5(s hav)23(e per)16(fect i)5(n)-1(fo)19(rmati)5(o)20(n)-1(.)]TJ
+0 -2.32 TD
+0.004 Tc
+(2.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.001 Tc
+0.001 Tw
+[(M)-6(obility is costless a)17(nd is r)14(e)-3(sponsive )20(only to fiscal c)21(onditions.)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+(3.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+0.538 Tw
+[(P)11(ubl)6(i)6(c)4( )20(goods )20(ar)17(e )20(pr)17(ovi)6(ded )20(at)22( mi)6(ni)6(mu)20(m ave)20(r)-3(age c)24(o)0(st w)6(i)6(t)2(hi)6(n e)20(a)0(ch)]TJ
+0 -1.16 TD
+0.003 Tc
+0.039 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on. )20( )20(E)10(a)-1(ch )20(new)5( mi)5(g)19(r)-4(ant t)21(o)-1( a co)19(mmuni)5(ty )20(pays an )20(access cost )20(equal)]TJ
+T*
+-0.001 Tw
+[(to the cost )20(of pr)16(ovi)5(d)-1(i)5(ng p)19(ubl)5(i)5(c)3( servi)5(c)3(es )20(to that)21( mi)5(gr)16(ant.)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+(4.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(There)20( are )20(no i)6(n)0(te)20(rj)6(uri)6(s)4(di)6(cti)6(o)20(nal)6( exte)20(rnal)6(i)6(t)2(i)6(e)0(s.)]TJ
+-2.36 -2.3 TD
+(5.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+0.138 Tw
+[(There)20( are )20(a suffi)6(ci)6(ent)22( num)17(ber of)22( j)6(u)0(ri)6(sdi)6(c)4(ti)6(ons)24( and a)20( )-20(suffi)6(ci)6(ent numb)20(e)0(r )-20(of)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(househol)5(ds )20(of each)19( type )20(\(i)5(n ter)16(m)-4(s of t)21(a)-1(stes and)19( )-20(i)5(n)-1(com)16(e)-1(s\) )-20(so )-20(t)21(hat )-20(e)19(a)-1(ch)]TJ
+-2.36 -2.78 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 106.64 m
+99.366 106.64 l
+S
+BT
+12 0 0 12 200.16 102.56 Tm
+( )Tj
+ET
+243.843 106.64 m
+200.163 106.64 l
+S
+BT
+10.08 0 0 10.08 99.36 90.685 Tm
+-0.008 Tc
+(25)Tj
+1.0952 -0.3095 TD
+0.016 Tw
+[( )-1428(Rubinf)-16(eld \()-8(1987\))-8( p.)-16( 575)]TJ
+ET
+endstream endobj 272 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 273 0 obj << /Type /Page /Parent 250 0 R /Resources 275 0 R /Contents 274 0 R >> endobj 274 0 obj << /Length 7134 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(59)Tj
+-31.96 58.98 TD
+0.003 Tc
+0.119 Tw
+[(j)5(u)-1(ri)5(sdi)5(c)3(ti)5(on can)19( contai)5(n i)25(denti)5(c)3(al)5( i)5(ndi)5(vi)25(dual)5(s. )20(Thus n)19(e)-1(w)5( )-20(comm)16(uni)5(ti)5(es )-20(can)]TJ
+0 -1.16 TD
+0 Tw
+[(be devel)4(op)18(ed costl)4(e)-2(ssl)4(y.)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+(6.)Tj
+0.84 -0.02 TD
+0 Tc
+( )Tj
+1.52 0.02 TD
+0.002 Tc
+0.24 Tw
+[(T)-7(her)-5(e)18( is no pu)18(blic )-20(choice m)-5(e)-2(chanis)22(m)-5( )-20(othe)18(r)-5( )-20(tha)18(n)-2( )-20(the utility-)-5(m)-5(a)-2(xi)24(m)-5(i)4(sing)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(deci)5(s)3(i)5(on of a)19(n)-1( i)5(denti)5(c)3(al)5( s)23(e)-1(t of i)5(n)19(di)5(vi)5(dual)5(s.)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+(7.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+0.018 Tw
+[(A)11(l)6(l)6( i)6(n)0(come i)6(s)4( di)6(vi)6(dend i)26(n)0(come,)22( not g)20(ener)17(ated by )20(pri)6(v)4(ate)20( pro)20(ducti)6(on. )20(The)20(r)-3(e)]TJ
+0 -1.16 TD
+-0.002 Tw
+[(i)6(s)4( no l)6(abou)20(r ma)20(rket.)]TJ
+-2.36 -2.3 TD
+(8.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.003 Tc
+-0.001 Tw
+[(P)10(ubl)5(i)5(c)3( goods ar)16(e fi)5(nanc)23(ed by l)5(u)19(mp su)19(m taxes.)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+(9.)Tj
+0.84 -0.02 TD
+0 Tc
+0 Tw
+( )Tj
+1.52 0.02 TD
+0.004 Tc
+-0.002 Tw
+[(There)20( i)6(s)4( no l)6(a)0(n)20(d)0(, no h)20(ousi)6(ng, )20(and th)20(eref)22(ore no)20( capi)6(tal)6(i)6(s)4(ati)26(on.)]TJ
+-2.36 -2.32 TD
+0.003 Tc
+0.279 Tw
+[(If )20(i)5(ndi)5(vi)5(dual)5(s )20(hav)23(e )20(any i)5(n)-1(f)21(o)-1(rm)16(ati)5(on a)19(bout l)5(o)-1(cal)5( p)19(ubl)5(i)5(c)3( go)19(ods an)19(d are)19( at al)5(l)]TJ
+0 -1.14 TD
+-0.001 Tc
+0.523 Tw
+[(m)-8(o)-5(b)-5(ile)-5(, )20(so)15(m)-8(e)-5( )20(p)-5(r)12(e)-5(f)-3(e)-5(r)-8(e)15(n)-5(ce)-5( )20(r)12(e)-5(ve)-5(la)-5(tio)-5(n)-5( will o)-5(c)-1(c)19(u)-5(r)-8( a)-5(n)15(d)-5( th)-5(e)15(r)-8(e)-5( will b)-5(e)-5( so)15(m)-8(e)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(competi)5(t)1(i)5(v)3(e )20(pressu)19(res am)16(ong j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.378 Tw
+[(The p)20(r)-3(efer)17(ence r)17(e)0(vel)6(a)0(ti)6(on)20( benefi)6(t)2(s)24( fro)20(m)-3( devol)6(uti)26(on de)20(ri)6(ve pa)20(rtl)6(y)4( )-20(fro)20(m)-3( )-20(the)]TJ
+0 -1.16 TD
+0.002 Tc
+0.04 Tw
+[(com)-5(petition )40(type )20(m)15(e)-2(chanis)22(m)-5(s )20(of )40(T)-7(i)4(ebout,)20( )20(that co)18(m)-5(e)-2( th)18(r)-5(oug)18(h m)-5(o)18(bility, and p)18(a)-2(r)-5(t)0(ly)]TJ
+0 -1.14 TD
+0.039 Tw
+[(from )20(i)5(m)16(prove)19(d)-1( )20(soci)5(al)5( choi)5(c)23(e)-1( mech)19(ani)5(sms i)5(n)-1( sm)16(al)5(l)5(e)-1(r j)25(u)-1(ri)5(sdi)5(c)3(ti)5(ons.)21( S)10(o)-1(ci)5(al)5( choi)5(ce)]TJ
+0 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(is m)-6(o)-3(r)-6(e)-3( im)14(p)-3(o)-3(r)-6(t)19(a)-3(n)-3(t)-1( in)-3( th)17(e)-3( sh)-3(o)17(r)-6(t r)-6(u)17(n)-3(.)-1( M)14(o)-3(b)-3(ility ta)-3(ke)-3(s e)17(ffe)-3(ct o)-3(v)1(e)17(r)-6( tim)14(e)-3(.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 440.72 Tm
+-0.017 Tc
+0.019 Tw
+[(M)-24(o)-26(b)-26(i)-19(li)-19(t)-24(y)-21( in)-26( N)-15(e)-21(w)-19( )20(Z)-26(e)-21(a)-21(l)-19(an)-26(d)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 414.56 Tm
+0 Tc
+0.262 Tw
+[(M)-7(o)-4(b)-4(ility is n)-4(o)-4(t)-2( c)20(o)-4(stle)-4(ss, a)-4(n)16(d)-4( is d)-4(e)-4(t)-2(e)16(r)-7(m)-7(i)2(n)-4(e)16(d)-4( b)-4(y)0( m)13(a)-4(n)-4(y)0( )-20(fa)-4(ct)18(o)-4(r)-7(s )-20(o)-4(t)-2(h)16(e)-4(r)-7( )-20(th)16(a)-4(n)-4( )-20(th)-4(e)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(provi)6(s)4(i)6(on )20(of )40(publ)6(i)6(c)4( )20(go)20(ods. )20( P)11(eopl)26(e devel)6(o)20(p)0( stro)20(ng attac)24(h)0(ment)22(s to a c)24(o)0(mmu)20(ni)6(ty.)]TJ
+T*
+0.018 Tw
+[(W)8(hen they d)20(o)0( move)20(, w)6(o)0(rk o)20(pport)22(uni)6(ti)6(es a)20(r)-3(e a m)17(a)0(j)6(o)0(r dri)6(v)4(er)17(. )-20( )-20(Th)20(us, )-20(not everyo)20(ne)]TJ
+T*
+0.003 Tc
+0.219 Tw
+[(moves w)5(hen)19(ever t)21(hey ar)16(e di)5(ssati)5(sfi)5(e)-1(d)19( w)5(i)5(t)1(h thei)25(r l)5(o)-1(cal)5( pu)19(bl)5(i)5(c)3( good )20(provi)5(s)3(i)5(o)-1(n)19(.)]TJ
+0 -1.14 TD
+0.119 Tw
+[(Those )20(w)5(h)-1(o)19( )20(do m)16(o)-1(ve m)16(a)-1(y not g)19(e)-1(t a l)5(e)-1(v)23(e)-1(l)5( of publ)5(i)5(c)3( )20(good )20(provi)5(s)3(i)5(on )20(they p)19(r)-4(efer)16(.)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(o)0(w)6( mobi)6(l)6(e)0( a)20(r)-3(e N)6(e)0(w)6( Z)15(eal)6(and)20(ers?)]TJ
+0 -2.32 TD
+0.118 Tw
+[(24%)13( )20(of )20(N)6(e)0(w)6( Zeal)26(ande)20(rs, l)6(i)6(v)4(i)6(ng i)6(n)0( N)6(e)0(w)6( )20(Zeal)6(and)20( i)6(n)0( 19)20(96, ha)20(d mov)24(ed i)6(n)0(to t)22(hei)6(r)]TJ
+0 -1.16 TD
+0.138 Tw
+[(current)22( ter)17(r)-3(i)6(t)2(ori)6(a)0(l)6( l)6(o)0(c)24(a)0(l)6( autho)20(ri)6(ty si)6(nce )20(1991 )20(\(N)6(Z C)6(ens)24(us, 199)20(6\). 5%)13( )-20(of )-20(these)]TJ
+0 -1.14 TD
+0.198 Tw
+[(w)6(e)0(re comi)6(n)20(g)0( fro)20(m)-3( ove)20(r)-3(seas, )-20(w)6(h)0(i)6(l)6(e)0( 19%)13( )-20(had moved )-20(f)22(r)-3(om el)6(sew)6(her)17(e )-20(i)6(n)0( )-20(N)6(e)0(w)]TJ
+0 -1.16 TD
+0.218 Tw
+[(Zeal)6(and.)22( Thi)6(s)4( )20(means )20(that a)20(pproxi)26(m)-3(atel)6(y o)20(ne i)6(n)0( )-20(eve)20(r)-3(y )-20(fou)20(r)-3( )-20(peo)20(pl)6(e )-20(ha)20(d )-20(the)]TJ
+T*
+0.003 Tc
+0.319 Tw
+[(chance, )20(cons)23(trai)5(ne)19(d by e)19(m)-4(pl)5(oyme)19(nt op)19(portu)19(ni)5(ti)5(es, to c)23(hoose t)21(hei)5(r l)5(e)-1(vel)5( )20(of)]TJ
+T*
+0.004 Tc
+-0.022 Tw
+[(publ)6(i)6(c)4( )-20(servi)6(c)4(e provi)6(s)4(i)6(on over )-20(t)22(he )-20(fi)6(ve-y)24(ear peri)6(od 1991 - )-20(199)20(6.)]TJ
+0 -2.3 TD
+0.118 Tw
+[(N)6(e)0(w)6( )20(Zeal)6(an)20(d )20(i)6(s)4( )20(a )20(smal)6(l)6( )20(c)24(ountry)24( w)6(i)6(t)2(h few)6( l)6(a)20(rge ci)6(ti)6(es s)24(o)0( the p)20(o)0(tenti)6(a)0(l)6( f)22(o)0(r l)6(a)20(rge)]TJ
+0 -1.16 TD
+0.278 Tw
+[(numbe)20(rs of j)6(u)20(ri)6(sdi)6(c)4(ti)6(ons off)22(e)0(ri)6(ng )20(a w)6(i)6(de r)17(ange o)20(f)2( l)6(e)0(vel)6(s)4( of )20(publ)6(i)6(c)4( go)20(ods i)6(s)]TJ
+T*
+0.418 Tw
+[(l)6(i)6(m)-3(i)6(t)2(ed. )20( )20(Ma)20(ny )20(of )20(th)20(e )20(publ)6(i)6(c)4( )40(goods i)6(n)0( N)26(e)0(w)6( Zeal)6(a)20(nd, th)20(at the R)26(e)0(sourc)24(e)]TJ
+T*
+0.278 Tw
+[(Manage)20(ment A)11(c)4(t i)6(s)4( co)20(ncern)20(ed w)6(i)6(t)2(h, a)20(r)-3(e r)17(e)0(l)6(a)0(ted t)22(o)0( nat)22(ure. )20(Thus t)22(hey a)20(r)-3(e)]TJ
+T*
+0.098 Tw
+[(geogra)20(phi)6(cal)6(l)6(y)4( )20(const)22(r)-3(ai)6(ned)20( )20(and )20(may not)22( easi)6(l)6(y)4( be )20(al)6(tere)20(d by l)6(o)0(cal)6( g)20(o)0(vern)20(ment)]TJ
+0 -1.14 TD
+0.003 Tc
+[(acti)5(on.)]TJ
+0 -2.32 TD
+0.004 Tc
+[(On the ot)22(her h)20(and, t)22(here )20(are si)6(g)20(n)0(i)6(f)2(i)6(c)4(ant cul)6(t)22(ural)6( di)6(ff)22(erenc)24(es betw)6(e)20(en )-20(ru)20(ral)6( )-20(an)20(d)]TJ
+0 -1.16 TD
+0.003 Tc
+0.159 Tw
+[(urban )20(a)19(r)-4(eas, )20(and a)19(m)-4(ong )20(rur)16(a)-1(l)5( are)19(a)-1(s such as N)25(o)-1(rthl)5(a)19(nd, W)7(a)-1(i)5(k)3(ato)19( and Ot)21(ago.)]TJ
+T*
+0.439 Tw
+[(There)19( )20(are )40(di)5(ffere)19(nces i)5(n)-1( cul)5(t)21(ure w)5(i)5(t)1(hi)5(n)19( ci)5(ti)5(es, e.g)19(.: the N)5(o)19(rth S)10(h)-1(o)19(r)-4(e vs.)]TJ
+ET
+endstream endobj 275 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 276 0 obj << /Length 8497 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(60)Tj
+-34.32 58.98 TD
+0.458 Tw
+[(W)8(a)0(i)6(t)2(akere. )20(The)20(r)-3(e ar)17(e cul)6(t)2(ur)17(al)6( di)6(ffe)20(rences b)20(e)0(tw)6(een )20(pred)20(omi)6(nan)20(tl)6(y )-20(mao)20(r)-3(i)]TJ
+0 -1.16 TD
+-0.002 Tw
+[(communi)6(ti)6(es)24( and p)20(a)0(keha c)24(o)0(mm)17(uni)6(ti)6(es. )20(Ther)17(e )-20(i)6(s)4( )-20(pro)20(babl)6(y )-20(g)20(r)-3(eate)20(r)-3( )-20(het)22(eroge)20(nei)6(ty)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(betw)5(een )20(co)19(mmuni)5(ti)25(es )20(than)19( )20(w)5(i)5(t)1(hi)5(n )20(the)19(m)-4(. T)14(hese cul)5(t)21(ural)5( di)5(ff)21(erenc)23(es ar)16(e l)5(i)5(k)3(el)5(y to)]TJ
+T*
+0.039 Tw
+[(be refl)5(ect)21(ed i)5(n)-1( th)19(e natu)19(r)-4(e of)21( publ)5(i)5(c)3( go)19(ods )-20(chose)19(n)-1(, )-20(an)19(d )-20(the atti)5(tudes to )-20(res)23(ource)]TJ
+0 -1.14 TD
+0.004 Tc
+[(regul)6(ati)6(o)0(n)20(.)2( Th)20(ere )20(al)6(so ar)17(e si)6(gni)6(fi)6(cant i)26(n)0(come )-20(d)20(i)6(ffer)17(ences )-20(be)20(tw)6(een )-20(co)20(mmuni)6(ti)26(es)]TJ
+0 -1.16 TD
+0.003 Tc
+0.059 Tw
+[(w)5(h)-1(i)5(c)3(h i)5(s)3( refl)5(ecte)19(d i)5(n)-1( the)19( l)5(e)-1(vel)5( of l)5(o)-1(c)23(a)-1(l)5( publ)5(i)5(c)3( g)19(oods e.)21(g.: Ma)19(nukau vs.)21( )-20(A)10(u)-1(ckl)5(and)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(C)6(i)6(t)2(y. Over ti)6(m)17(e)0(, peo)20(pl)6(e \(p)20(arti)6(cul)6(a)20(rl)6(y the yo)20(ung a)20(nd i)6(mmi)26(grants)24(\))-3( mov)24(e)0( )-20(to )-20(n)20(e)0(w)]TJ
+T*
+[(j)6(obs )20(and )20(th)20(ei)6(r )20(choi)6(c)24(e)0(s )20(of )20(l)6(o)0(cati)26(on ar)17(e pa)20(rtl)6(y)4( dete)20(rmi)6(ne)20(d by the)20( \223cul)6(tu)20(re\224 )20(of the)]TJ
+T*
+0.002 Tc
+0.04 Tw
+[(ar)-5(eas. )20( )20(Cities )20(that p)18(r)-5(ovide )20(an att)20(r)-5(active \223)-5(c)22(ultur)-5(e)18(\224)-5( will gr)-5(ow )20(and b)18(e)-2( r)-5(e)-2(wa)18(r)-5(ded with)]TJ
+0 -1.14 TD
+0.004 Tc
+-0.022 Tw
+[(l)6(a)0(rger reven)20(ue )-20(bases)24(.)]TJ
+0 -2.32 TD
+0.002 Tc
+0.06 Tw
+[(Gr)-5(adual )20(m)-5(obility, an)18(d existing cl)24(uster)-5(s)2( )20(of )-20(sim)-5(ilar)-5( people,)20( )-20(m)-5(e)-2(a)18(n)-2(s )-20(that devolutio)18(n)]TJ
+0 -1.16 TD
+0.079 Tw
+[(does have )20(the po)19(tenti)5(a)-1(l)5( t)21(o)-1( provi)5(d)19(e a w)5(i)5(d)-1(e)19(r)-4( ra)19(nge )-20(of publ)5(i)5(c)3( )-20(go)19(ods )-20(w)5(h)-1(i)5(c)3(h )-20(sa)19(ti)5(sfy)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(di)6(verse co)20(mmuni)6(ty )20(prefe)20(r)-3(ences)24( i)6(n)0( N)6(e)0(w)6( Z)15(eal)6(and. )20( H)6(o)0(w)6(e)0(ver )20(peopl)6(e)20( w)6(ho do move)]TJ
+0 -1.14 TD
+0.178 Tw
+[(are )20(not )40(rep)20(r)-3(esent)22(ati)6(v)4(e of t)22(he total)6( )20(popul)6(a)20(t)2(i)6(on. F)15(o)0(r ex)24(ampl)6(e,)22( they te)20(nd to )20(be)]TJ
+0 -1.16 TD
+0.218 Tw
+[(younger.)22( If th)20(e provi)6(s)4(i)6(o)20(n of p)20(ubl)6(i)6(c)4( goods)24( does )20(respon)20(d to th)20(e de)20(mands o)20(f)]TJ
+T*
+0.002 Tc
+0.06 Tw
+[(people who )20(m)-5(o)-2(ve, )20(they will not )20(r)-5(e)-2(flect t)20(he p)18(r)-5(efer)15(ences of)20( the sta)18(b)-2(le )-20(com)15(m)-5(unity)]TJ
+T*
+-0.001 Tc
+0.343 Tw
+[(m)-8(e)-5(m)-8(b)-5(e)15(r)-8(s. Po)-5(licie)-5(s to)-5( in)-5(c)19(r)-8(e)-5(a)-5(s)-1(e)-5( )20(m)-8(o)-5(b)-5(ility )20(m)-8(a)-5(y im)-8(p)15(r)-8(o)-5(v)-1(e)-5( th)15(e)-5( m)-8(a)-5(tc)19(h)-5( )-20(b)-5(e)-5(t)-3(we)15(e)-5(n)]TJ
+T*
+0.002 Tc
+0.04 Tw
+[(pr)-5(efer)15(ences )20(a)18(nd )20(public )40(goods, )40(and will cer)15(t)0(ainly lead )20(to m)-5(o)18(r)-5(e)-2( effici)24(ent allocati)24(on)]TJ
+0 -1.14 TD
+0.459 Tw
+[(of l)5(abour)16(, but i)5(t)1( )20(al)5(so has s)23(o)-1(ci)5(al)5( )-20(di)5(sadva)19(n)-1(tages. )-20(The)19( )-20(soci)5(al)5( )-20(capi)5(t)21(a)-1(l)5( )-20(i)5(n)]TJ
+0 -1.16 TD
+0.22 Tw
+[(com)-5(m)-5(unities)22( m)-5(a)-2(y b)18(e)-2( one )20(of thei)24(r)-5( pr)-5(i)24(m)-5(ar)-5(y a)18(ttr)-5(actio)18(n)-2(s, )-20(yet )-20(exc)22(e)-2(ssive )-20(m)-5(o)18(bility)]TJ
+T*
+0 Tw
+[(tends to d)18(e)-2(stroy i)4(t)20(.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 426.8 Tm
+0.004 Tc
+-0.002 Tw
+[(P)11(r)13(o)-5(b)-5(l)2(em)13(s with)-5( )20(Mo)15(b)-5(ilit)17(y an)15(d)-5( E)11(ffi)22(cien)15(cy)]TJ
+/F5 1 Tf
+0.4634 -2.18 TD
+0.003 Tc
+-0.001 Tw
+[(E)10(ffects of Fi)5(na)19(nci)5(ng P)10(ubl)5(i)5(c)3( Go)19(od P)10(r)-4(ovi)5(s)3(i)5(on )20(on E)10(ffi)5(ci)5(ent )20(Mi)5(grati)5(o)19(n P)10(a)-1(tter)16(n)-1(s)]TJ
+12 0 0 12 99.36 374.72 Tm
+[(P)10(ubl)5(i)5(c)3( good pr)16(ovi)5(s)3(i)5(on, an)19(d the )20(taxes associ)25(ated w)5(i)5(t)1(h i)5(t)21(, not )-20(o)19(n)-1(l)5(y)3( )-20(sati)5(sfi)5(e)-1(s )-20(a )-20(s)23(t)1(ati)5(c)]TJ
+0 -1.16 TD
+0.039 Tw
+[(demand )20(for se)19(rvi)5(c)3(es, th)19(ey al)5(so g)19(ener)16(ate a dyn)19(a)-1(mi)5(c respons)23(e. )-20( )-20(If )-20(u)19(nanti)5(c)3(i)5(pat)21(ed,)]TJ
+0 -1.14 TD
+[(thi)5(s)3( )20(dynami)5(c)3( )20(f)21(eedback)23( )20(coul)5(d )20(l)5(e)-1(a)19(d)-1( )20(to d)19(a)-1(magi)5(ng)19( res)23(u)-1(l)5(t)1(s. In t)21(he cont)21(ext of t)21(he N)5(Z)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(R)6(e)0(source )20(Manag)20(ement)22( A)11(c)4(t, publ)6(i)6(c)4( go)20(ods a)20(r)-3(e )-20(pr)17(ovi)6(ded )-20(t)22(h)0(roug)20(h )-20(re)20(gul)6(ati)6(on rathe)20(r)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(than gove)19(r)-4(nm)16(ent p)19(r)-4(ovi)5(s)3(i)5(on. R)5(a)-1(t)21(e)-1(s cove)19(r the )-20(ad)19(mi)5(ni)5(st)21(rati)5(ve )-20(costs of )-20(desi)5(g)19(ni)5(ng)]TJ
+T*
+0.079 Tw
+[(and i)5(m)-4(pl)5(e)19(m)-4(enti)5(n)-1(g)19( reg)19(u)-1(l)5(a)-1(ti)5(ons, b)19(u)-1(t thi)5(s)3( i)5(s)3( a)19( )-20(smal)5(l)5( )-20(fr)16(acti)5(on )-20(of)21( )-20(the )-20(t)21(o)-1(tal)5( )-20(econ)19(omi)5(c)]TJ
+T*
+0.279 Tw
+[(cost. Impl)5(i)5(c)3(i)5(t)1(l)5(y)3(, l)5(o)-1(c)23(a)-1(l)5( gove)19(r)-4(nmen)19(t fi)5(nanc)23(es provi)5(s)3(i)5(o)19(n )-20(by )-20(\223t)21(aki)5(ng\224 resou)19(r)-4(ces.)]TJ
+0 -1.14 TD
+0.039 Tw
+[(Li)5(mi)5(ti)5(ng )20(the )40(acti)5(vi)5(ti)5(es )20(al)5(l)5(o)-1(w)5(e)-1(d)19( on p)19(r)-4(i)5(v)3(ate l)5(a)-1(n)19(d)-1( i)5(m)-4(pos)23(es costs. )20(To th)19(e exten)19(t)1( that)]TJ
+0 -1.16 TD
+0.179 Tw
+[(thi)5(s)3( cost i)5(s)3( cor)16(r)-4(el)5(ated)19( w)5(i)5(t)1(h pr)16(operty)23( val)5(ues, i)5(t)1( )20(oper)16(ates i)5(n)-1( a si)25(mi)5(l)5(a)-1(r )-20(w)5(a)-1(y to )-20(a)]TJ
+T*
+0 Tc
+0.162 Tw
+[(p)-4(r)-7(o)-4(p)-4(e)16(r)-7(t)-2(y )20(ta)-4(x. )20( We)-4( will sta)16(r)-7(t b)-4(y)0( lo)16(o)-4(k)0(in)-4(g)-4( a)-4(t)18( th)-4(e)-4( e)-4(f)18(fe)-4(cts o)-4(f)-2( )20(p)-4(r)-7(o)-4(p)16(e)-4(r)-7(ty ta)-4(x)20(e)-4(s o)-4(n)-4( t)18(h)-4(e)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(effi)5(ci)5(ency )20(of )20(d)19(e)-1(vol)5(u)-1(ti)5(on, )40(and )20(t)21(hen r)16(e)-1(turn)19( to the )20(di)5(ffer)16(ence b)19(e)-1(tw)5(een t)21(a)-1(x provi)5(s)3(i)25(o)-1(n)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(and reg)20(u)0(l)6(a)0(tory)24( provi)6(s)4(i)6(o)20(n.)]TJ
+0 -2.3 TD
+0.003 Tc
+-0.001 Tw
+[(W)7(hen every )20(perso)19(n pays a)19(n)-1( equ)19(al)5( amo)19(unt fo)19(r publ)5(i)5(c)3( )-20(se)19(rvi)5(c)3(es, )-20(po)19(or )-20(p)19(eopl)5(e )-20(h)19(a)-1(ve)]TJ
+0 -1.16 TD
+0.004 Tc
+0.018 Tw
+[(no i)6(n)0(centi)6(v)4(e t)22(o)0( mov)24(e)0( )-20(fro)20(m)-3( )-20(a )-20(ho)20(moge)20(neous poor di)6(stri)6(ct )-20(w)6(i)6(t)2(h )-20(l)6(o)0(w)6( publ)6(i)6(c)4( )-20(se)20(rvi)6(c)4(es)]TJ
+T*
+0.058 Tw
+[(and a l)6(o)0(w)6( ch)20(arge )20(to a hi)6(g)20(h)0(-i)6(nco)20(m)-3(e di)6(st)22(ri)6(ct w)6(i)6(t)2(h )-20(hi)6(gh)20( )-20(publ)6(i)6(c)4( )-20(se)20(rvi)6(c)4(es )-20(and)20( )-20(a )-20(hi)6(gh)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(charge. )20( W)7(i)5(th pro)19(perty )20(taxes, h)19(o)-1(w)5(e)-1(ver, )20(a poor)16( pe)19(rson ca)19(n buy a s)23(m)-4(al)5(l)5( ho)19(use i)5(n)]TJ
+0 -1.14 TD
+0.04 Tw
+[(a r)-5(i)4(ch distr)-5(i)4(ct)20(, enjoy t)20(he bet)20(ter)-5( p)18(ublic ser)-5(v)2(ices a)18(nd still p)18(a)-2(y a low a)18(m)-5(ount.)20( )-20( )-20(If )-20(the)]TJ
+0 -1.16 TD
+0.399 Tw
+[(cost )20(of )20(publ)5(i)5(c)3( )20(s)23(e)-1(rvi)5(c)3(es ri)5(s)23(e)-1(s w)5(i)5(t)1(h the)19( num)16(ber of)21( peopl)25(e \(as a)19( resul)5(t)1( )20(of)]TJ
+T*
+0.019 Tw
+[(congesti)5(on, )20(or p)19(r)-4(i)5(v)3(ate as)23(pects of )20(the pu)19(bl)5(i)5(c)3( servi)5(c)3(e)19(\))-4(, )-20(thi)5(s)3( )-20(di)5(sa)19(dvanta)19(ges )-20(the ri)5(ch)]TJ
+T*
+0.08 Tw
+[(people. )20(T)-7(hey will eithe)18(r)-5( wish to )20(m)-5(o)-2(ve t)20(o)-2( anot)20(her)-5( a)18(r)-5(ea )20(as poo)18(r)-5( peo)18(ple ente)18(r)-5(, )-20(o)18(r)]TJ
+ET
+endstream endobj 277 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 278 0 obj << /Type /Pages /Kids [ 109 0 R 279 0 R 112 0 R 284 0 R 287 0 R 114 0 R 292 0 R 116 0 R 297 0 R 300 0 R ] /Count 10 /Parent 151 0 R >> endobj 279 0 obj << /Type /Page /Parent 278 0 R /Resources 281 0 R /Contents 280 0 R >> endobj 280 0 obj << /Length 9216 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(61)Tj
+-34.32 58.98 TD
+0.002 Tc
+0.08 Tw
+[(will tr)-5(y to exclude)18( the p)18(oor)-5( p)18(eople. One )-20(way )-20(excl)24(usion )-20(is )-20(do)18(ne )-20(is )-20(by )-20(zo)18(ning )-20(a)]TJ
+0 -1.16 TD
+0.004 Tc
+0.098 Tw
+[(mi)6(ni)6(mum st)22(anda)20(rd of )20(housi)6(ng s)24(o)0( the)20(r)-3(e i)6(s)4( no l)26(o)0(w)6( i)6(n)0(come)20( housi)6(n)0(g)20( )-20(avai)6(l)6(abl)6(e. )-20(If)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(ri)5(cher )20(co)19(mmuni)5(ti)25(es do n)19(o)-1(t excl)5(ud)19(e poo)19(rer p)19(eopl)5(e, )20(prop)19(erty tax)23(e)-1(s can )20(make th)19(e)]TJ
+T*
+0.159 Tw
+[(composi)5(t)1(i)5(on )40(of )20(com)16(m)-4(uni)5(ti)5(es, )40(and )20(h)19(ence th)19(e l)5(e)-1(vel)5( of )20(publ)5(i)5(c)3( go)19(ods pr)16(ovi)5(ded i)5(n)]TJ
+0 -1.24 TD
+0.004 Tc
+-0.002 Tw
+[(them, uns)24(tabl)6(e ov)24(er ti)6(m)17(e)0(.)]TJ
+10.08 0 0 10.08 234 692.365 Tm
+-0.008 Tc
+(26)Tj
+12 0 0 12 99.36 661.52 Tm
+0.004 Tc
+0.038 Tw
+[(Thi)6(s)4( pro)20(b)0(l)6(e)0(m i)6(s)4( )20(reduce)20(d)0( by th)20(e phen)20(omen)20(on of \223capi)6(tal)6(i)6(s)4(ati)26(on\224. )-20( The )-20(v)24(a)0(l)6(ue )-20(of a)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(house de)19(pends n)19(o)-1(t onl)5(y o)19(n)-1( i)5(t)1(s physi)5(cal)5( c)23(haract)21(e)-1(ri)5(sti)5(cs, b)19(u)-1(t al)5(so )-20(o)19(n)-1( )-20(the bundl)5(e of)]TJ
+0 -1.14 TD
+0.139 Tw
+[(publ)5(i)5(c)3( servi)5(c)3(es )20(ow)5(nershi)5(p)19( \(o)19(r occupa)19(ncy i)5(n)-1( the)19( case of)21( rent)21(al)5(\) enti)5(t)1(l)25(e)-1(s you )-20(to)]TJ
+0 -1.16 TD
+-0.001 Tc
+0.063 Tw
+[(co)-5(n)-5(s)-1(u)-5(m)-8(e)-5(.)-3( )20( A co)-5(m)-8(m)-8(u)15(n)-5(i)1(ty with)-5( g)-5(o)15(o)-5(d)-5( p)-5(u)15(b)-5(lic se)-5(r)-8(v)-1(ice)-5(s)-1( will a)-5(l)1(so)-5( )20(h)-5(a)-5(v)-1(e)-5( h)-5(i)1(g)15(h)-5(e)-5(r)-8( )-20(h)15(o)-5(u)-5(s)-1(e)]TJ
+T*
+0.002 Tc
+0.02 Tw
+[(pr)-5(ices. With p)18(e)-2(r)-5(f)0(ect c)22(apitalisation)18(,)0( a po)18(or)-5( )-20(pe)18(r)-5(s)2(on )-20(will )-20(be)18( )-20(indiffer)15(ent )-20(b)18(e)-2(tween )-20(t)20(h)-2(e)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(ri)6(ch )20(and )20(p)20(oor )20(nei)6(ghbo)20(urho)20(ods bec)24(ause al)6(t)22(hough )20(the ri)6(c)24(h)0( nei)6(gh)20(bour)17(hood h)20(a)0(s)]TJ
+T*
+0.158 Tw
+[(better se)20(rvi)6(c)4(es, th)20(e hous)24(e pri)6(c)4(es )20(are )20(al)6(so hi)6(ghe)20(r. C)6(api)6(t)22(a)0(l)6(i)6(s)4(ati)6(on reduces the)]TJ
+0 -1.14 TD
+0.002 Tc
+0.02 Tw
+[(instability of co)18(m)-5(m)-5(unities)22(, but d)18(oes not)20( ensu)18(r)-5(e efficiency)22(,)0( eithe)18(r)-5( in p)18(r)-5(oductio)18(n)-2( )-20(or)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(i)5(n)-1( the l)5(e)-1(vel)5( of)21( publ)5(i)5(c)3( go)19(od, w)5(i)5(t)1(hi)5(n )20(hete)19(r)-4(ogen)19(eous co)19(mmuni)5(ti)5(es)23(.)]TJ
+0 -2.32 TD
+0.159 Tw
+[(H)5(o)-1(w)5( )20(do these c)23(oncl)5(u)-1(si)5(ons v)23(a)-1(ry w)5(h)-1(e)19(n)-1( provi)5(s)3(i)5(o)-1(n)19( i)5(s)3( achi)5(ev)23(ed by r)16(egul)5(ati)5(o)19(n not)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(taxati)6(on? C)6(o)0(s)24(t)2( bea)20(ri)6(ng i)6(s)4( no)20(t rel)6(a)0(t)22(ed now)6( )-20(t)22(o)0( )-20(the )-20(v)24(a)0(l)6(ue )-20(of the )-20(p)20(r)-3(ope)20(rty. )-20( )-20(It rel)6(a)0(tes)]TJ
+0 -1.14 TD
+0.003 Tc
+0.199 Tw
+[(to )20(the eff)21(e)-1(cts of p)19(r)-4(i)5(v)3(ate )20(acti)5(vi)5(ti)5(es on t)21(hat p)19(r)-4(oper)16(ty on t)21(he pr)16(ovi)5(s)3(i)5(on of )20(publ)5(i)5(c)]TJ
+0 -1.16 TD
+0.279 Tw
+[(goods. )20( )20( )40(For )20(exampl)5(e)19(,)1( thi)5(n)-1(k of)21( a com)16(pany th)19(at w)5(oul)5(d l)5(i)5(k)3(e)19( to pol)5(l)5(u)-1(t)21(e)-1(. B)10(y)]TJ
+T*
+0.219 Tw
+[(restri)5(cti)5(ng )20(i)5(t)1(s)23( )20(pol)5(l)5(u)-1(ti)5(on )40(the r)16(egul)5(ati)5(o)19(n i)5(m)-4(pos)23(es a cost )20(on the)19( comp)19(any. T)14(h)-1(e)]TJ
+T*
+0.004 Tc
+0.118 Tw
+[(company ca)20(n mov)24(e)0( to an)20(othe)20(r are)20(a)0( w)6(i)6(t)2(h l)6(e)0(ss st)22(ri)6(ngent)22( reg)20(u)0(l)6(a)0(ti)6(on o)20(r)-3( can bear)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(the )20(cost )20(an)19(d ul)5(ti)5(ma)19(tel)5(y)3( pass i)5(t)1( )20(on to t)21(hei)5(r custo)19(m)-4(e)19(r)-4(s. If t)21(he l)5(and )20(the co)19(mpany)]TJ
+0 -1.14 TD
+0 Tc
+0.222 Tw
+[(u)-4(s)0(e)-4(s)0( ca)-4(n)-4( b)-4(e)16( u)-4(s)0(e)-4(d)-4( f)18(o)-4(r)-7( m)13(a)-4(n)-4(y)0( p)-4(u)16(r)-7(p)-4(o)-4(s)0(e)-4(s)0(, i)22(t)-2(s va)-4(lu)-4(e)-4( will n)-4(o)-4(t)18( b)-4(e)-4( a)-4(f)-2(f)18(e)-4(cte)-4(d)-4( )20(b)-4(y)0( th)-4(is)]TJ
+0 -1.16 TD
+0.004 Tc
+0.038 Tw
+[(regul)6(ati)6(o)0(n)20(.)2( If th)20(ere a)20(r)-3(e ot)22(her )20(areas t)22(o)0( pr)17(oduce, )-20(t)22(he )-20(cost of )-20(the regul)26(ati)6(on )-20(i)6(s)4( )-20(l)6(o)0(w)]TJ
+T*
+0.002 Tc
+0.16 Tw
+[(because th)18(e com)15(pany will m)-5(o)-2(v)22(e)-2(. In a)18(n)-2(y case )-20(t)20(h)-2(is )-20(is )-20(an )-20(ex)22(am)-5(ple of )-20(pollute)18(r)]TJ
+T*
+0.139 Tw
+[(pays, )20(w)5(here)19( )20(an )20(ext)21(e)-1(rnal)5(i)5(t)1(y )20(i)5(s)3( i)25(n)-1(tern)19(al)5(i)5(s)3(ed. )20(Thi)5(s)3( i)5(s)3( effi)5(ci)5(en)19(t and )20(often se)19(en as)]TJ
+T*
+0.001 Tc
+0.001 Tw
+[(equitable. N)23(o)-3( com)14(m)-6(unity inst)19(ability issues a)17(r)-6(ise.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.279 Tw
+[(A)10( more co)19(mpl)5(e)-1(x case )20(ari)5(s)3(es w)5(h)19(ere a)19(n)-1( acti)5(vi)5(ty on)19( )-20(a )-20(pi)5(ece)19( )-20(of )-20(l)5(and)19( )-20(affects)]TJ
+0 -1.16 TD
+0.004 Tc
+0.078 Tw
+[(provi)6(s)4(i)6(on of )20(a posi)6(t)2(i)6(v)4(e )20(exter)17(nal)6(i)6(t)2(y or )20(publ)6(i)6(c)4( go)20(od. Tw)26(o pi)6(eces of )-20(l)6(and )-20(c)24(oul)6(d )-20(be)]TJ
+T*
+0.058 Tw
+[(i)6(denti)6(c)4(al)6( )20(except)22( )20(that )20(o)20(ne )20(i)6(s)4( chos)24(en fo)20(r envi)6(r)17(onme)20(n)0(tal)6( or)17( hi)6(stori)6(c)4(al)6( c)24(onserv)24(a)0(ti)6(on.)]TJ
+T*
+0.002 Tc
+0.02 Tw
+[(T)-7(he value)18( of th)18(e chosen)18( land will fall. )20(T)-7(he own)18(e)-2(r)-5( o)18(f)0( the ch)18(osen )-20(la)18(nd )-20(at )-20(t)20(he )-20(tim)-5(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.038 Tw
+[(of )20(the )20(r)17(egul)6(ati)6(o)20(n )20(i)6(s)4( har)17(med w)6(h)0(i)6(l)6(e)0( )20(the ow)6(n)20(e)0(r of t)22(he i)6(d)0(e)20(n)0(ti)6(cal)6( pi)6(ece i)6(s)4( )20(not. )20(Thi)6(s)4( i)6(s)]TJ
+0 -1.16 TD
+0.018 Tw
+[(cal)6(l)6(ed )20(\223taki)6(n)20(gs\224 )20(i)6(n)0( )20(th)20(e U)6(S)11(. A)11( smal)6(l)6( gr)17(oup of)22( unfo)20(r)-3(tunat)22(e l)6(andow)26(ners a)20(r)-3(e b)20(eari)6(n)0(g)]TJ
+T*
+0.003 Tc
+0.099 Tw
+[(al)5(l)5( )20(the )20(costs )20(of)21( )20(provi)5(d)-1(i)25(ng a g)19(ood, w)5(h)-1(i)5(c)3(h)19( w)5(e)-1( al)5(l)5( enj)5(oy.)21( If eac)23(h reg)19(u)-1(l)5(a)-1(ti)5(on h)19(a)-1(s a)]TJ
+T*
+0.004 Tc
+0.198 Tw
+[(smal)6(l)6( i)6(m)-3(pact )20(on each)20( i)6(ndi)6(vi)6(dual)6(, )20(and a l)26(a)0(rge )20(numb)20(e)0(r of )20(di)6(ffer)17(ent r)17(egul)6(ati)6(ons)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(affect di)5(ffe)19(rent i)5(n)19(di)5(vi)5(dual)5(s, thi)5(s)3( )20(al)5(l)5( comes )20(out i)5(n)-1( t)21(he )-20(w)5(a)-1(sh, but )-20(i)5(t)1( )-20(i)5(s)3( )-20(n)19(o)-1(t )-20(al)5(w)5(a)-1(ys )-20(th)19(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.158 Tw
+[(case. U)6(nde)20(r the R)26(M)-3(A)11(,)2( these l)6(a)20(nd use )20(restri)6(cti)6(o)20(n rel)26(a)0(ted costs)24( )-20(are al)6(l)6( )-20(born)20(e)]TJ
+0 -1.16 TD
+0.178 Tw
+[(through)20( )20(capi)6(tal)6(i)6(s)4(ati)6(o)20(n. )20( )20(T)15(he )20(ow)6(ne)20(r )20(of t)22(he ho)20(use at t)22(he ti)6(me)20( of the)20( reg)20(u)0(l)6(a)0(ti)6(on)]TJ
+T*
+0.003 Tc
+0.079 Tw
+[(cannot avoi)25(d the cos)23(t)1( of cu)19(rren)19(t)1( reg)19(u)-1(l)5(a)-1(ti)5(on by)23( movi)5(ng)19( )-20(aw)5(ay. )-20( )-20(Mi)25(grants)23( )-20(i)5(n)-1(to )-20(th)19(e)]TJ
+T*
+0.099 Tw
+[(ar)-4(ea pay)23( the cos)23(t)1( of th)19(e )-20(bene)19(fits )-20(thr)16(ough )-20(hi)25(gher)-4( house )-20(v)23(a)-1(lues. )-20( T)-6(he )-20(RM)-4(A)10( )-20(will)]TJ
+T*
+-0.001 Tw
+[(not l)5(ead t)21(o)-1( unsta)19(bl)5(e com)16(m)-4(uni)5(ti)5(es.)]TJ
+0 -2.08 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 141.2 m
+99.366 141.2 l
+S
+BT
+12 0 0 12 200.16 137.12 Tm
+( )Tj
+ET
+243.843 141.2 m
+200.163 141.2 l
+S
+BT
+10.08 0 0 10.08 99.36 125.485 Tm
+-0.008 Tc
+(26)Tj
+1.0952 -0.3095 TD
+0.206 Tw
+[( )-1238(A)-8(not)-16(her)-8( is)-8(s)-8(ue whic)-8(h c)-8(an lead t)-16(o)0( z)-8(oning in r)-8(i)0(c)-8(h)0( ar)-8(eas)16( is)-8( )-24(t)-16(hat)8( )-24(poor)-8(er)-8( )-24(people )-24(ar)-8(e )-24(of)-16(t)-16(e)0(n)]TJ
+1.7143 -1.1905 TD
+0.182 Tw
+[(as)-8(s)-8(o)0(c)-8(iat)-16(ed )23(wit)-16(h )23(par)-8(t)-16(i)0(c)-8(ular)-8( )23(negat)-16(iv)-8(e )26(ex)-8(t)-16(e)0(r)-8(nalt)-16(it)-16(ies)-8(,)8( )23(s)-8(u)0(c)-8(h)0( as)16( unt)-16(idy)-8( gar)-8(dens)-8(,)-16( old c)-8(a)0(r)-8(s)16( et)-16(c)16(.)]TJ
+0 -1.1429 TD
+0.063 Tw
+[(Ric)-8(h )23(people )23(m)-8(a)0(y)-8( )23(t)-16(r)-8(y)-8( )47(t)-16(o)0( )23(indir)-8(ec)-8(t)-16(l)0(y)-8( )23(c)-8(ont)-16(r)-8(ol )47(t)-16(hes)-8(e ex)-8(t)-16(e)0(r)-8(nalit)-16(ies)-8( by)16( r)-8(ais)-8(ing lot)-16( s)-8(i)0(z)-8(e)0(s)-8( and henc)-8(e)]TJ
+T*
+0.016 Tw
+[(ex)-8(c)-8(luding poor)-8( peopl)-24(e.)]TJ
+ET
+endstream endobj 281 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 282 0 obj << /Length 9301 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(62)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.007 Tc
+-0.005 Tw
+[(A)9(ppen)18(d)-2(i)5(x)3( )20(Fo)18(ur)16(: O)5(t)20(her)16( E)14(x)3(ter)16(n)-2(al)5(i)25(t)0(i)5(e)3(s)]TJ
+12 0 2.551 12 99.36 719.6 Tm
+0.004 Tc
+-0.002 Tw
+[(Tax ex)20(ter)13(n)-5(ali)22(t)-3(ies)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 693.44 Tm
+0.003 Tc
+0.419 Tw
+[(A)10( si)5(mi)5(l)5(a)-1(r i)5(ssue to t)21(he eff)21(e)-1(cts of )20(regul)5(ati)5(o)19(n on m)16(i)5(grati)25(on, i)5(s)3( tha)19(t)1( of tax)]TJ
+0 -1.16 TD
+0.179 Tw
+[(external)5(i)5(t)1(i)5(e)-1(s.)21( )20( )20(W)7(here )40(ther)16(e are)19( non-c)23(onstan)19(t)1( retu)19(rns to)19( scal)5(e)-1( i)5(n)-1( p)19(ubl)5(i)5(c)3( goo)19(ds)]TJ
+T*
+0 Tc
+0.102 Tw
+[(p)-4(r)-7(o)-4(v)0(isio)-4(n)-4(,)-2( )20(m)-7(i)2(g)-4(r)-7(a)-4(t)-2(io)16(n)-4( o)-4(f)-2( in)-4(d)-4(i)2(vid)16(u)-4(a)-4(l)2(s will a)-4(ffe)-4(ct )20(th)-4(e)-4( ta)-4(x )20(b)-4(u)-4(r)-7(d)16(e)-4(n)-4(s)0( in)-4( th)16(e)-4(i)2(r)-7( o)16(r)-7(ig)-4(in)-4( a)-4(n)16(d)]TJ
+T*
+0.003 Tc
+0.199 Tw
+[(desti)5(nati)5(on c)23(o)-1(mmu)19(ni)5(ti)5(es. In)19(di)5(vi)5(dual)5(s pay the )-20(ave)19(r)-4(age)19(, )-20(not margi)25(nal)5(, )-20(costs )-20(o)19(f)]TJ
+0 -1.14 TD
+0.339 Tw
+[(publ)5(i)5(c)3( )20(goods.)21( )20(B)10(e)-1(cause e)19(a)-1(ch i)5(ndi)5(vi)5(du)19(al)5( reg)19(a)-1(rds t)21(he tax st)21(ructu)19(r)-4(e as fi)5(xe)19(d,)]TJ
+0 -1.16 TD
+0.099 Tw
+[(i)5(neffi)5(ci)5(ent )20(outc)23(o)-1(mes )20(c)23(oul)5(d )20(occu)19(r. S)10(upp)19(ose an i)5(n)19(di)5(vi)5(dual)5( m)16(o)-1(ves out)21( of a s)23(m)-4(al)5(l)]TJ
+T*
+0.199 Tw
+[(communi)5(ty w)5(i)5(t)21(h l)5(o)-1(w)5( ma)19(rgi)5(nal)5( cos)23(t)1(s but hi)25(gh )-20(ave)19(r)-4(age )-20(c)23(o)-1(sts. )-20( )-20(T)14(hey )-20(r)16(a)-1(i)5(s)3(e )-20(the)]TJ
+T*
+0.004 Tc
+0.198 Tw
+[(average c)24(o)0(st of )20(publ)6(i)6(c)4( goo)20(d pr)17(ovi)6(s)4(i)6(on fo)20(r the )20(remai)6(n)0(i)26(ng com)17(m)-3(uni)6(ty. )-20(If )-20(they)]TJ
+T*
+0.003 Tc
+0.019 Tw
+[(move i)5(n)-1(to )20(a l)5(a)-1(rg)19(e com)16(m)-4(uni)5(ty w)5(h)-1(e)19(r)-4(e av)23(erage)19( costs a)19(r)-4(e )-20(l)5(o)-1(w)5( )-20(but)21( )-20(publ)5(i)5(c)3( )-20(g)19(oods )-20(a)19(r)-4(e)]TJ
+0 -1.14 TD
+0 Tw
+[(congested s)22(o)-2( m)-5(a)18(r)-5(g)-2(inal cos)22(t)0(s ar)-5(e )20(high, t)20(hey will r)-5(a)-2(ise t)20(he cost t)20(her)-5(e)18( )-20(as )-20(well. )-20( T)-7(h)-2(e)]TJ
+0 -1.16 TD
+[(individual ben)18(efits fr)-5(o)18(m)-5( the)18( m)-5(o)-2(ve; s)22(o)-2(ciety loses.)20( F)-7(i)4(gu)18(r)-5(e)-2( 4 illust)20(r)-5(a)-2(tes t)20(he eff)20(e)-2(ct )-20(of)]TJ
+T*
+-0.001 Tw
+[(communi)5(ty si)5(z)23(e)-1( on av)23(erag)19(e, ma)19(rgi)5(nal)5( a)19(nd tot)21(a)-1(l)5( costs.)]TJ
+/F3 1 Tf
+0 -2.82 TD
+0.005 Tc
+-0.003 Tw
+[(Figur)14(e )20(8 E)12(c)1(o)16(nom)14(ies a)21(nd D)7(i)23(seco)16(nom)14(ies)21( of S)12(c)1(a)21(l)3(e in)16( C)7(o)-4(m)14(m)14(unit)18(y)1( S)12(i)3(ze)]TJ
+ET
+0 0 0 RG
+1 J 1 j 0.72 w 10 M []0 d
+1 i
+135.36 473.6 m
+135.36 332.24 l
+S
+0.24 w
+132.96 472.64 m
+137.76 472.64 l
+135.36 476.24 l
+132.96 472.64 l
+b*
+0.72 w
+135.36 332.24 m
+377.52 332.24 l
+S
+0.24 w
+376.56 334.64 m
+376.56 329.84 l
+380.16 332.24 l
+376.56 334.64 l
+b*
+BT
+/F5 1 Tf
+12 0 0 12 100.32 463.76 Tm
+0 Tc
+0 Tw
+($)Tj
+21 -12.6 TD
+0.003 Tc
+-0.001 Tw
+[(S)10(i)5(ze of comm)16(uni)5(ty)]TJ
+ET
+1.92 w
+250.56 404.24 m
+186.97 404.24 135.36 397.735 135.36 389.72 c
+135.36 389.68 135.361 389.64 135.364 389.6 c
+250.559 404.24 m
+306.117 404.287 351.12 436.509 351.12 476.24 c
+S
+171.12 397.04 0.48 -0.96 re
+f*
+171.12 394.16 0.48 -0.96 re
+f*
+171.12 391.28 0.48 -0.96 re
+f*
+171.12 388.4 0.48 -0.96 re
+f*
+171.12 385.52 0.48 -0.96 re
+f*
+171.12 382.64 0.48 -0.96 re
+f*
+171.12 379.76 0.48 -0.96 re
+f*
+171.12 376.88 0.48 -0.96 re
+f*
+171.12 374 0.48 -0.96 re
+f*
+171.12 371.12 0.48 -0.96 re
+f*
+171.12 368.24 0.48 -0.96 re
+f*
+171.12 365.36 0.48 -0.96 re
+f*
+171.12 362.48 0.48 -0.96 re
+f*
+171.12 359.6 0.48 -0.96 re
+f*
+171.12 356.72 0.48 -0.96 re
+f*
+171.12 353.84 0.48 -0.96 re
+f*
+171.12 350.96 0.48 -0.96 re
+f*
+171.12 348.08 0.48 -0.96 re
+f*
+171.12 345.2 0.48 -0.96 re
+f*
+171.12 342.32 0.48 -0.96 re
+f*
+171.12 339.44 0.48 -0.96 re
+f*
+171.12 336.56 0.48 -0.96 re
+f*
+171.12 333.68 0.48 -0.96 re
+f*
+336.72 440.24 0.48 -0.96 re
+f*
+336.72 437.36 0.48 -0.96 re
+f*
+336.72 434.48 0.48 -0.96 re
+f*
+336.72 431.6 0.48 -0.96 re
+f*
+336.72 428.72 0.48 -0.96 re
+f*
+336.72 425.84 0.48 -0.96 re
+f*
+336.72 422.96 0.48 -0.96 re
+f*
+336.72 420.08 0.48 -0.96 re
+f*
+336.72 417.2 0.48 -0.96 re
+f*
+336.72 414.32 0.48 -0.96 re
+f*
+336.72 411.44 0.48 -0.96 re
+f*
+336.72 408.56 0.48 -0.96 re
+f*
+336.72 405.68 0.48 -0.96 re
+f*
+336.72 402.8 0.48 -0.96 re
+f*
+336.72 399.92 0.48 -0.96 re
+f*
+336.72 397.04 0.48 -0.96 re
+f*
+336.72 394.16 0.48 -0.96 re
+f*
+336.72 391.28 0.48 -0.96 re
+f*
+336.72 388.4 0.48 -0.96 re
+f*
+336.72 385.52 0.48 -0.96 re
+f*
+336.72 382.64 0.48 -0.96 re
+f*
+336.72 379.76 0.48 -0.96 re
+f*
+336.72 376.88 0.48 -0.96 re
+f*
+336.72 374 0.48 -0.96 re
+f*
+336.72 371.12 0.48 -0.96 re
+f*
+336.72 368.24 0.48 -0.96 re
+f*
+336.72 365.36 0.48 -0.96 re
+f*
+336.72 362.48 0.48 -0.96 re
+f*
+336.72 359.6 0.48 -0.96 re
+f*
+336.72 356.72 0.48 -0.96 re
+f*
+336.72 353.84 0.48 -0.96 re
+f*
+336.72 350.96 0.48 -0.96 re
+f*
+336.72 348.08 0.48 -0.96 re
+f*
+336.72 345.2 0.48 -0.96 re
+f*
+336.72 342.32 0.48 -0.96 re
+f*
+336.72 339.44 0.48 -0.96 re
+f*
+336.72 336.56 0.48 -0.96 re
+f*
+336.72 333.68 0.48 -0.96 re
+f*
+BT
+12 0 0 12 157.92 312.56 Tm
+[(sm)16(al)5(l)-9675(l)5(ar)16(ge)]TJ
+ET
+0.96 w
+135.36 332.24 m
+336.96 440.24 l
+300.96 389.84 m
+372.96 483.44 l
+S
+BT
+12 0 0 12 373.92 456.56 Tm
+0.001 Tc
+0.001 Tw
+[(M)14(a)-3(r)-6(g)-3(inal cost)]TJ
+-12.6 -8.4 TD
+0.003 Tc
+-0.001 Tw
+[(A)10(v)3(erage cost)]TJ
+ET
+0.72 w
+257.76 368.24 m
+231.36 381.44 l
+S
+0.24 w
+231.12 379.04 m
+233.04 383.12 l
+228.96 382.64 l
+231.12 379.04 l
+b*
+0.72 w
+372.96 461.84 m
+361.2 461.84 l
+S
+0.24 w
+361.92 459.44 m
+361.92 464.24 l
+358.56 461.84 l
+361.92 459.44 l
+b*
+BT
+12 0 0 12 186.72 442.16 Tm
+0.001 Tc
+0.001 Tw
+[(T)12(o)-3(tal cost)]TJ
+ET
+0.72 w
+214.56 433.04 m
+214.56 406.88 l
+S
+0.24 w
+216.96 407.6 m
+212.16 407.6 l
+214.56 404.24 l
+216.96 407.6 l
+b*
+BT
+12 0 0 12 99.36 284.96 Tm
+0.003 Tc
+0.019 Tw
+[(W)7(hen )20(publ)5(i)5(c)3( go)19(ods a)19(r)-4(e fi)5(nanc)23(ed w)5(i)5(t)1(h p)19(r)-4(ope)19(rty taxes)23( \(or)16( othe)19(r const)21(r)-4(ai)5(nts, w)5(h)-1(i)5(c)3(h)]TJ
+0 -1.16 TD
+0.004 Tc
+0.258 Tw
+[(affect )20(ri)6(che)20(r)-3( )20(pe)20(opl)6(e m)17(o)0(re\))17( and t)22(here i)6(s)4( c)24(ongesti)6(o)20(n)0( i)6(n)0( pu)20(bl)6(i)6(c)4( goods,)22( a poo)20(r)]TJ
+0 -1.14 TD
+0.178 Tw
+[(person )20(movi)6(ng i)6(n)0(t)22(o)0( a ri)6(c)24(her j)6(u)20(ri)6(sdi)6(c)4(ti)6(on c)24(r)-3(eates )20(a )-20(\223fi)6(scal)6( )-20(ex)24(tern)20(al)6(i)6(t)2(y\224 )-20(bec)24(ause)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(they contri)25(bute l)5(e)-1(ss )20(than t)21(he ma)19(rgi)5(nal)5( c)23(o)-1(st of th)19(e publ)5(i)5(c)3( g)19(ood.)]TJ
+0 -2.32 TD
+0.32 Tw
+[(B)9(e)-2(cause )20(r)-5(e)-2(so)18(ur)-5(ce )40(r)-5(e)-2(lated)18( )20(public )20(go)18(ods a)18(r)-5(e pr)-5(o)18(v)2(ided by)22( contr)15(o)-2(lling activity)]TJ
+0 -1.16 TD
+0.099 Tw
+[(rather)16( )20(than )40(by )20(taxi)5(ng, )20(these t)21(a)-1(x exte)19(rnal)5(i)5(t)1(i)5(e)-1(s do)19( not occ)23(u)-1(r di)25(rectl)5(y)3(. H)5(o)-1(w)5(e)-1(v)23(e)-1(r a)]TJ
+0 -1.14 TD
+0.004 Tc
+0.018 Tw
+[(rel)6(a)0(ted p)20(r)-3(obl)6(e)20(m)-3( does)24( occur.)22( A)11( mi)6(gra)20(n)0(t goi)6(n)20(g)0( fro)20(m)-3( a )-20(l)6(o)0(w)6(-)-3(d)20(ensi)6(t)2(y )-20(a)20(r)-3(ea )-20(t)22(o)0( )-20(a )-20(hi)6(gh)20(-)]TJ
+0 -1.16 TD
+0.003 Tc
+0.219 Tw
+[(densi)5(t)1(y are)19(a)-1( re)19(duces ext)21(e)-1(rnal)5(i)5(t)1(i)5(e)-1(s v)23(e)-1(ry l)5(i)5(ttl)5(e by )-20(l)5(eavi)5(ng the )-20(l)5(o)-1(w)5(-)-4(d)19(ensi)5(t)1(y )-20(a)19(r)-4(ea)]TJ
+T*
+0.299 Tw
+[(\(margi)25(nal)5( exte)19(rnal)5(i)5(t)1(i)5(e)-1(s a)19(r)-4(e sm)16(al)5(l)5(\))-4(. W)7(h)-1(e)19(n)-1( movi)5(ng)19( )-20(i)5(n)-1(to )-20(a hi)5(gh-d)19(ensi)5(t)1(y )-20(a)19(r)-4(ea,)]TJ
+T*
+0.059 Tw
+[(how)5(ever, )20(t)21(he )20(ma)19(rgi)5(nal)5( )40(effect )20(o)19(n)-1( pol)5(l)5(u)-1(ti)5(o)19(n)-1( and o)19(t)1(her)16( exter)16(nal)5(i)5(t)1(i)5(e)-1(s coul)5(d)19( be m)16(u)-1(ch)]TJ
+T*
+[(hi)5(gher th)19(an th)19(e aver)16(age cost)21( the i)5(ndi)5(vi)5(d)19(ual)5( bea)19(rs. S)10(o)-1(ci)5(ety may )-20(suff)21(er )-20(f)21(r)-4(om )-20(th)19(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(move )20(w)6(h)0(i)6(l)6(e)0( th)20(e i)6(ndi)6(vi)6(dual)6( )20(benefi)6(t)2(s.)22( Fo)20(r exa)20(m)-3(pl)6(e, a)20(n)0( addi)6(ti)6(o)20(nal)6( pe)20(rson m)17(o)0(vi)6(ng)]TJ
+0 -1.16 TD
+0.003 Tc
+0.519 Tw
+[(to C)5(h)-1(ri)5(stchu)19(r)-4(ch i)5(n)-1(cr)16(eases ai)25(r pol)5(l)5(u)-1(ti)5(o)19(n)-1(, w)5(h)-1(i)5(c)3(h aff)21(e)-1(cts )-20(eve)19(r)-4(y )-20(resi)5(d)19(ent )-20(of)]TJ
+T*
+0.004 Tc
+0.238 Tw
+[(C)6(h)0(ri)6(stchurch)20(. )20( )20(A)11(s)4( )20(w)6(e)0(l)6(l)6( as affec)24(t)2(i)6(ng m)17(any peo)20(pl)6(e, da)20(mage )20(from)17( ai)6(r p)20(o)0(l)6(l)6(u)0(ti)6(on)]TJ
+ET
+endstream endobj 283 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 284 0 obj << /Type /Page /Parent 278 0 R /Resources 286 0 R /Contents 285 0 R >> endobj 285 0 obj << /Length 7150 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(63)Tj
+-34.32 58.98 TD
+0.003 Tc
+0.279 Tw
+[(tends to b)19(e)-1( non)19(-l)5(i)5(near)16(, so th)19(e extra)19( pol)5(l)5(u)-1(ti)5(on)19( causes )20(much m)16(o)-1(re t)21(han th)19(e)]TJ
+0 -1.16 TD
+0.004 Tc
+-0.022 Tw
+[(average dama)20(ge.)]TJ
+0 -2.32 TD
+0.002 Tc
+0.04 Tw
+[(M)-5(obility and c)22(hoice of j)24(u)-2(r)-5(i)4(sdictions )20(ar)-5(e lim)-5(it)20(ed, an)18(d the )20(gr)-5(ou)18(p that does )-20(m)15(o)-2(ve )-20(is)]TJ
+0 -1.14 TD
+0.1 Tw
+[(non-)-5(r)15(epr)-5(ese)18(n)-2(tative. )40( )20(T)-7(hus)22( jur)-5(i)4(sdictions)22( will be still be int)20(e)-2(r)-5(nally h)18(e)-2(ter)15(ogene)18(ous,)]TJ
+0 -1.16 TD
+0.56 Tw
+[(and a pu)18(r)-5(e)-2(ly en)18(tr)-5(ep)18(r)-5(eneu)18(r)-5(i)4(al local g)18(o)-2(ver)-5(n)18(m)-5(ent will m)-5(i)4(s)22(r)-5(epr)15(esent s)22(o)-2(cial)]TJ
+T*
+0.18 Tw
+[(pr)-5(efer)15(ences. )20( )40(M)-5(obility )20(can)18( )20(also )20(r)15(educe e)18(fficiency bec)22(ause of)20( the ext)20(e)-2(r)-5(nalities)]TJ
+T*
+0.004 Tc
+0.098 Tw
+[(mi)6(grants c)24(r)-3(eat)22(e. Th)20(e publ)6(i)6(c)4( c)24(hoi)6(ce m)17(e)0(chani)6(sms )20(used w)6(i)6(t)2(hi)6(n)20( j)6(u)0(ri)6(sdi)6(c)4(ti)6(ons)24(, )-20(and)]TJ
+T*
+0.003 Tc
+0.279 Tw
+[(how)5( w)5(e)-1(l)5(l)5( they r)16(e)-1(fl)5(ect cons)23(ti)5(tuent )20(prefe)19(r)-4(ences)23(, are c)23(r)-4(i)5(t)1(i)5(c)3(al)5( fo)19(r assessi)5(ng)19( the)]TJ
+0 -1.14 TD
+-0.001 Tw
+[(effecti)5(v)3(eness )20(of devol)5(u)19(t)1(i)5(on.)]TJ
+0 -2.32 TD
+0.039 Tw
+[(The eff)21(e)-1(cti)5(v)3(eness )20(of deci)5(s)3(i)5(ons )20(al)5(so de)19(pends on)19( how)5( )-20(w)5(e)-1(l)5(l)5( )-20(th)19(e )-20(pol)5(i)5(t)1(i)5(c)3(al)5( )-20(i)5(n)-1(sti)5(t)21(uti)5(o)-1(n)]TJ
+0 -1.16 TD
+0.139 Tw
+[(refl)5(ects be)19(nefi)5(t)1(s an)19(d costs, h)19(o)-1(w)5( w)5(e)-1(l)5(l)5( obj)5(ecti)5(ve)19( )-20(i)5(n)-1(for)16(m)-4(ati)5(on )-20(i)5(s)3( used )-20(to)19( )-20(i)5(m)-4(pr)16(ove)]TJ
+T*
+0.279 Tw
+[(the )20(qual)5(i)5(t)1(y )20(o)19(f)1( )20(deci)5(s)3(i)5(on )40(maki)5(ng, )40(and h)19(o)-1(w)5( cost-ef)21(f)1(ecti)5(ve t)21(he deci)5(s)3(i)5(o)-1(n)19( maki)5(ng)]TJ
+0 -1.14 TD
+0 Tc
+0.002 Tw
+[(p)-4(r)-7(o)-4(c)0(e)-4(ss itse)-4(lf is.)]TJ
+/F3 1 Tf
+12 0 2.551 12 99.36 523.76 Tm
+0.003 Tc
+-0.001 Tw
+[(ln)-6(ter)12(j)1(u)-6(r)12(is)19(d)-6(i)1(cti)21(o)-6(n)-6(a)19(l Co)-6(m)12(p)-6(e)19(t)-4(iti)21(o)-6(n)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 497.84 Tm
+0.019 Tw
+[(W)7(hen ther)16(e are)19( hete)19(r)-4(ogen)19(eous )20(regul)5(ati)5(o)19(ns acr)16(o)-1(ss j)5(u)-1(ri)5(sdi)5(c)3(ti)5(o)19(n)-1(s, both)19( l)5(abou)19(r and)]TJ
+0 -1.16 TD
+0.001 Tc
+0.421 Tw
+[(capital )20(will )20(choose )20(t)19(he m)-6(o)-3(s)21(t)-1( attr)14(active jur)-6(i)3(s)21(d)-3(iction. )20(T)-8(h)-3(is cr)-6(e)17(a)-3(tes he)17(althy)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(competi)6(t)2(i)6(on )20(amon)20(g j)6(u)0(ri)6(sdi)6(c)4(ti)6(o)20(n)0(s, but c)24(an al)6(so c)24(r)-3(eat)22(e tw)6(o pr)17(obl)6(ems.)22( )-20(Th)20(e )-20(fi)6(rst)]TJ
+T*
+0.003 Tc
+0.139 Tw
+[(probl)5(em)16( ari)5(s)3(es i)5(f)1( )20(the sup)19(p)-1(l)5(y)3( of capi)5(t)21(a)-1(l)5( i)5(s)3( very e)19(l)5(asti)5(c to )20(each j)5(u)-1(ri)5(s)23(d)-1(i)5(c)3(ti)5(on, )-20(i)5(.)1(e.)]TJ
+T*
+0.099 Tw
+[(very mobi)5(l)5(e)19(, and s)23(e)-1(veral)5( j)5(u)19(ri)5(sdi)5(c)3(ti)5(ons t)21(r)-4(y to )20(attract i)5(t)21( si)5(mul)5(t)1(an)19(eousl)5(y)3(. )-20( Thi)5(s)3( )-20(can)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(l)6(ead to a )20(\223race)20( to the)20( botto)20(m\224 i)6(n)0( l)26(o)0(cal)6( publ)6(i)6(c)4( go)20(od p)20(r)-3(ovi)6(s)4(i)6(on. E)11(a)0(c)24(h)0( )-20(j)6(u)0(ri)6(sdi)6(c)4(ti)6(o)20(n)]TJ
+0 -1.16 TD
+0.003 Tc
+0.219 Tw
+[(offers sl)5(i)5(ghtl)5(y)3( )20(mor)16(e)-1( attr)16(acti)5(ve con)19(d)-1(i)5(t)1(i)5(ons to )20(attract)21( the el)5(as)23(ti)5(c capi)5(tal)5(.)1( )-20( Other)]TJ
+T*
+0.001 Tc
+0.141 Tw
+[(jur)-6(i)3(sdictions r)14(e)-3(spond wit)19(h m)-6(o)17(r)-6(e)-3( att)19(r)-6(active co)17(nditions still \()-6(l)3(ower)-6( )-20(t)19(a)-3(xes )-20(or)-6( m)-6(o)-3(r)14(e)]TJ
+T*
+0.004 Tc
+0.018 Tw
+[(l)6(eni)6(ent )20(envi)6(r)17(onme)20(n)0(tal)6( )20(r)17(egul)6(ati)6(ons)24(\) )20(l)6(eadi)26(ng )20(to a )20(dow)6(nw)6(a)20(r)-3(d spi)6(r)17(al)6(. Thi)6(s)4( c)24(an occu)20(r)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(even i)5(f)1( the j)25(u)-1(ri)5(sdi)5(c)3(ti)5(on )20(has a g)19(o)-1(vern)19(ment that )-20(re)19(pres)23(ents )-20(th)19(e )-20(consti)5(tu)19(ents\222)]TJ
+0 -1.24 TD
+0.001 Tc
+[(inter)-6(e)-3(sts.)]TJ
+10.08 0 0 10.08 148.08 360.925 Tm
+-0.008 Tc
+(27)Tj
+12 0 0 12 159.12 357.92 Tm
+0.002 Tc
+0 Tw
+[( No jur)-5(i)4(sdiction)18( bene)18(fits fr)-5(o)18(m)-5( this in e)18(quilibr)-5(i)4(u)18(m)-5(.)]TJ
+-4.98 -2.32 TD
+0.004 Tc
+0.038 Tw
+[(The seco)20(nd pr)17(obl)6(em )20(ari)6(s)4(es i)6(f)2( t)22(he l)6(o)0(cal)6( j)6(u)20(ri)6(sdi)6(c)4(ti)6(on ac)24(ts as an entr)17(epre)20(neur, and)]TJ
+0 -1.16 TD
+0.003 Tc
+0.199 Tw
+[(maxi)5(mi)5(ses i)5(t)1(s )20(revenu)19(e rat)21(her th)19(an r)16(epres)23(enti)5(ng co)19(nsti)5(tuent)21( )-20(i)5(n)-1(ter)16(e)-1(sts. )-20( )-20(If )-20(o)19(n)-1(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.358 Tw
+[(factor )20(i)6(s)4( con)20(s)4(i)6(dere)20(d)0( to be)20( mo)20(re mo)20(bi)6(l)6(e)0(, the )20(deci)6(s)4(i)6(on-m)17(a)0(ke)20(rs may )20(desi)6(g)0(n)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(regul)5(ati)5(ons)23( )20(to )20(att)21(r)-4(act )20(th)19(at )20(fact)21(or )20(at t)21(he exp)19(ense of)21( the ot)21(her. )20( One ex)23(ampl)5(e )20(of)]TJ
+T*
+0.14 Tw
+[(this is lax envir)-5(o)18(n)-2(m)-5(ent)20(al r)-5(e)-2(g)18(u)-2(lation t)20(o)-2( attr)15(act m)-5(a)18(nufactu)18(r)-5(i)4(ng. )20(Labou)18(r)-5( )-20(will )-20(only)]TJ
+T*
+0.159 Tw
+[(respond sl)25(ow)5(l)5(y)3( to the)19( poo)19(rer e)19(n)-1(vi)5(ron)19(m)-4(ental)5( )20(qual)5(i)5(t)1(y, )-20(w)5(h)-1(i)5(l)5(e)-1( )-20(ca)19(pi)5(tal)5( )-20(may)23( )-20(fl)5(ow)5( )-20(i)5(n)]TJ
+T*
+0.259 Tw
+[(qui)5(ckl)5(y, )20(l)5(eadi)5(ng t)21(o)-1( sho)19(r)-4(t ru)19(n reve)19(nue b)19(enefi)5(t)1(s. )20(Thi)5(s)3( can)19( al)5(so occu)19(r at t)21(h)-1(e)]TJ
+0 -1.14 TD
+0.004 Tc
+0.098 Tw
+[(nati)6(onal)6( )20(l)6(e)0(vel)6( )40(and )20(coul)26(d )20(be ev)24(en mo)20(re ac)24(ute bec)24(ause i)6(n)0(t)22(e)0(rnati)6(o)20(nal)6(l)6(y)4(, l)6(abo)20(ur i)6(s)]TJ
+0 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(l)5(e)-1(ss mobi)5(l)5(e)-1( th)19(an capi)5(t)21(a)-1(l)5(.)]TJ
+0 -8.76 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 118.16 m
+99.366 118.16 l
+S
+BT
+12 0 0 12 200.16 114.08 Tm
+( )Tj
+ET
+243.843 118.16 m
+200.163 118.16 l
+S
+BT
+10.08 0 0 10.08 99.36 102.205 Tm
+-0.008 Tc
+(27)Tj
+1.0952 -0.3095 TD
+0.087 Tw
+[( )-1357(T)-16(his)-8( c)-8(an als)-8(o oc)-8(c)-8(u)0(r)15( on t)-16(he nat)-16(ional s)-8(c)-8(ale but)-16( m)-8(a)0(y)-8( )-24(be )-24(les)-8(s)16( )-24(ac)-8(ut)-16(e )-24(bec)-8(aus)-8(e )-24(c)-8(apit)-16(al )-24(is)-8( )-24(les)-8(s)]TJ
+1.7143 -1.1667 TD
+0.016 Tw
+[(m)-8(obile bet)-16(ween t)-16(han wit)-16(hin c)-8(ount)-16(r)-8(ies)-8(.)]TJ
+ET
+endstream endobj 286 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 287 0 obj << /Type /Page /Parent 278 0 R /Resources 289 0 R /Contents 288 0 R >> endobj 288 0 obj << /Length 3818 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(64)Tj
+/F3 1 Tf
+12 0 2.551 12 99.36 731.84 Tm
+-0.002 Tw
+[(\223N)6(ot in m)13(y)0( )20(back)20(yar)13(d\224 N)6(I)2(MB)6(Y)]TJ
+/F5 1 Tf
+12 0 0 12 99.36 705.92 Tm
+0.158 Tw
+[(Thi)6(s)4( i)6(s)4( a co)20(mmonl)6(y )20(observ)24(ed phe)20(nome)20(non w)6(h)0(e)20(r)-3(e ev)24(ery )-20(co)20(mmuni)6(ty opposes)]TJ
+0 -1.16 TD
+0.003 Tc
+0.059 Tw
+[(housi)5(ng )20(an)19( acti)5(vi)5(ty w)5(i)5(t)1(h n)19(egati)5(v)3(e l)5(o)-1(c)23(a)-1(l)5( exter)16(nal)5(i)5(t)1(i)5(e)-1(s, bu)19(t posi)5(t)1(i)5(v)3(e )20(net be)19(nefi)5(t)1(s fo)19(r)]TJ
+T*
+0.259 Tw
+[(soci)5(ety as a w)5(hol)25(e. T)14(h)-1(i)5(s)3( pro)19(b)-1(l)5(e)-1(m )-20(do)19(es )-20(not ari)5(s)3(e )-20(b)19(e)-1(cause of )-20(the )-20(l)5(e)-1(v)23(e)-1(l)5( )-20(of)]TJ
+T*
+0.039 Tw
+[(deci)5(s)3(i)5(on maki)5(n)19(g)-1(, tho)19(ugh i)5(t)1( ca)19(n be )20(\223sol)5(ved\224)16( by )-20(cent)21(ral)5( )-20(gov)23(ernm)16(ent )-20(fi)5(at.)21( )-20( )-20(It )-20(a)19(r)-4(i)5(s)3(es)]TJ
+T*
+0.219 Tw
+[(because )20(exi)5(s)3(ti)5(n)19(g)-1( )20(mec)23(hani)5(sms )40(are )20(i)5(n)-1(a)19(dequ)19(ate fo)19(r comp)19(ensati)5(n)-1(g)19( the a)19(ffected)]TJ
+0 -1.14 TD
+0.719 Tw
+[(groups. )20(D)5(e)-1(v)23(o)-1(l)5(u)-1(ti)5(on )20(makes t)21(hese i)5(ssues )20(mor)16(e)-1( vi)5(si)5(bl)5(e, bec)23(ause l)5(o)-1(cal)]TJ
+0 -1.16 TD
+0.199 Tw
+[(communi)5(ti)5(es)23( )20(have )40(more s)23(a)-1(y, but)21( may n)19(o)-1(t w)5(o)-1(rse)19(n)-1( the )20(outcom)16(e)-1(s. A)10(l)5(thou)19(gh)]TJ
+T*
+[(si)5(ti)5(ng may b)19(e)-1( mo)19(re di)5(ffi)5(cul)5(t, )20(and p)19(o)-1(ssi)5(bl)5(y )-20(l)5(e)-1(ss )-20(effi)5(ci)5(e)19(n)-1(t, )-20(the outco)19(mes )-20(und)19(er)]TJ
+T*
+-0.001 Tw
+[(devol)5(uti)5(on )20(may be )20(fai)5(r)-4(e)19(r)-4( i)5(f)1( com)16(pensati)5(n)19(g deal)5(s ca)19(n be )20(made.)]TJ
+0 -2.3 TD
+0.059 Tw
+[(A)10( )20(cl)5(osel)5(y )20(rel)5(a)-1(ted )20(i)5(ssu)19(e )20(i)5(s)3( )20(that)21( of \223e)19(nvi)5(r)-4(on)19(mental)5( j)25(u)-1(sti)5(c)3(e\224. )20(Thi)5(s)3( i)5(s)3( a c)23(oncer)16(n that)]TJ
+0 -1.16 TD
+0 Tw
+[(local autho)18(r)-5(i)4(ties place )20(a dispr)15(opor)-5(ti)24(onate )20(num)-5(b)18(e)-2(r)-5( of l)24(andfills, toxic)22(-)-5(waste )-20(du)18(m)-5(p)-2(s,)]TJ
+T*
+0.1 Tw
+[(and othe)18(r)-5( un)18(attr)-5(active)18( public facilities i)24(n)-2( poo)18(r)-5( and )20(m)-5(i)4(nor)-5(ity)22( neigh)18(bour)-5(h)18(oods. )-20( If)]TJ
+T*
+0.004 Tc
+0.518 Tw
+[(thi)6(s)4( i)6(s)4( )-20(true, \(the evi)6(dence )-20(i)6(s)4( mi)6(xed\))17( )-20(and )-20(t)22(he )-20(com)17(m)-3(uni)6(ty recei)6(v)4(es no)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(compensati)25(on, i)5(t)1( m)16(a)-1(y be )20(a fai)5(l)5(u)-1(re)19( of th)19(e l)5(o)-1(cal)5( )-20(pu)19(bl)5(i)5(c)3( )-20(choi)5(ce )-20(m)16(e)-1(chani)5(s)23(m)-4(. )-20( )-20(It )-20(i)5(s)3( )-20(n)19(o)-1(t)]TJ
+0 -1.14 TD
+0.004 Tc
+0.058 Tw
+[(cl)6(ear w)6(heth)20(e)0(r dev)24(ol)6(uti)6(on w)6(o)20(rsens o)20(r)-3( i)6(m)-3(p)20(r)-3(oves t)22(h)0(i)6(s)4( pro)20(b)0(l)6(e)0(m. I)22(f)2( )-20(devol)6(uti)26(on )-20(go)20(es)]TJ
+0 -1.16 TD
+0.002 Tc
+0.16 Tw
+[(down )20(to )20(th)18(e )20(level of t)20(he m)-5(i)4(n)18(o)-2(r)-5(i)4(ty co)18(m)-5(m)-5(unity)22(, such f)20(a)-2(cilities cannot)20( be foist)20(e)-2(d)]TJ
+T*
+0.06 Tw
+[(upon )20(the)18(m)-5( )20(ag)18(ainst thei)24(r)-5( will. M)-5(i)4(no)18(r)-5(i)4(ties m)-5(a)-2(y)22( have a)18( str)-5(o)-2(n)18(ger)-5( voic)22(e in a s)22(m)-5(aller)]TJ
+T*
+0.004 Tc
+0.058 Tw
+[(communi)6(ty.)22( )20( )20(On )20(th)20(e )20(othe)20(r han)20(d, cent)22(ral)6( gov)24(ernm)17(ent i)6(s)4( of)22(ten a l)6(e)20(ader)17( i)6(n)0( verti)6(c)24(al)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(and raci)5(al)5( )20(equi)5(ty i)5(ssues)23(.)]TJ
+ET
+endstream endobj 289 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 290 0 obj << /Length 8019 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(65)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+0.007 Tc
+-0.005 Tw
+[(A)9(ppen)18(d)-2(i)5(x)3( )20(Fi)5(ve)23(: E)14(qui)25(tab)18(l)5(e s)23(h)-2(ar)16(i)5(ng )20(of )20(cos)23(t)0(s an)18(d )20(bene)23(fi)5(ts)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.178 Tw
+[(Local)6( )20(gove)20(r)-3(nme)20(n)0(t i)6(s)4( i)6(nhe)20(rentl)6(y)4( b)20(ad at )20(redi)6(stri)26(buti)6(ng i)6(n)0(c)24(o)0(me, f)22(o)0(r a )20(numb)20(e)0(r of)]TJ
+0 -1.14 TD
+0.003 Tc
+0.399 Tw
+[(reasons. )20(The )20(anal)5(ysi)5(s i)5(n)-1( t)21(he Ti)5(e)19(bout f)21(r)-4(amew)25(ork an)19(d )-20(the publ)5(i)5(c)3( )-20(choi)5(ce)]TJ
+0 -1.16 TD
+0.179 Tw
+[(framew)5(o)19(r)-4(k i)5(s)3( conce)19(r)-4(ned )20(pri)5(m)16(ari)5(l)5(y)3( w)5(i)5(t)1(h effi)5(ci)5(e)19(n)-1(cy not )20(equi)5(ty. )20(The l)5(i)5(t)1(e)19(r)-4(atur)16(e on)]TJ
+T*
+0.279 Tw
+[(l)5(o)-1(cal)5( publ)5(i)5(c)3( fi)5(nanc)23(e and )20(redi)5(st)21(ri)5(buti)5(on )20(deal)5(s w)5(i)5(t)1(h t)21(he eff)21(e)-1(cts of at)21(tempts)23( to)]TJ
+T*
+0.079 Tw
+[(redi)5(stri)5(bu)19(te )20(i)5(n)-1(co)19(me thr)16(ough )20(prog)19(ressi)5(ve tax)23(e)-1(s or )20(provi)5(s)3(i)5(o)-1(n)19( of pu)19(bl)5(i)5(c)3( goods i)5(n)19( a)]TJ
+T*
+0.004 Tc
+0.098 Tw
+[(l)6(o)0(cati)6(on or )20(of a ty)24(pe that)22( makes )20(them )20(mor)17(e)0( val)6(uabl)6(e)20( to po)20(orer)17( )-20(peopl)26(e. )-20( )-20(In )-20(t)22(h)0(e)]TJ
+0 -1.14 TD
+0.438 Tw
+[(case of res)24(ource)20( man)20(agem)17(ent w)6(e)0( a)20(r)-3(e no)20(t )-20(di)6(rectl)6(y)4( deal)6(i)6(ng )-20(w)6(i)6(t)2(h)20( )-20(i)6(n)0(come)]TJ
+0 -1.16 TD
+0.003 Tc
+0.199 Tw
+[(redi)5(stri)5(bu)19(ti)5(on, bu)19(t reso)19(urce )20(deci)5(s)3(i)5(ons do)19( affect t)21(he di)5(st)21(ri)5(buti)5(on )20(of w)5(eal)5(th and)]TJ
+T*
+0.004 Tc
+0.438 Tw
+[(i)6(n)0(come, )20(an)20(d )20(the )20(provi)6(s)4(i)6(o)0(n)20( and p)20(r)-3(otecti)26(on of pu)20(bl)6(i)6(c)4( goo)20(ds and c)24(o)0(mm)17(on)]TJ
+T*
+0.002 Tc
+0 Tw
+[(r)-5(e)-2(sour)-5(c)22(e)-2(s could h)18(a)-2(ve sim)-5(ila)18(r)-5( effects)22( to taxes)22(.)]TJ
+0 -2.3 TD
+0 Tc
+0.062 Tw
+[(L)-4(o)-4(c)0(a)-4(l)2( )20(g)-4(o)-4(v)0(e)16(r)-7(n)-4(m)-7(e)16(n)-4(ts h)-4(a)-4(v)0(e)-4( li)22(m)-7(i)2(te)-4(d)-4( a)16(b)-4(ility to)-4( r)-7(e)16(d)-4(i)2(str)-7(i)2(b)-4(u)-4(t)18(e)-4( with)-4(i)2(n)-4( th)16(e)-4(i)2(r)-7( co)16(m)-7(m)-7(u)-4(n)-4(i)2(ty.)18( If)]TJ
+0 -1.16 TD
+0.142 Tw
+[(a)-4( co)-4(m)-7(m)-7(u)16(n)-4(i)2(ty h)-4(a)-4(s)0( )20(m)-7(o)-4(r)-7(e)-4( )20(p)-4(r)-7(o)-4(g)16(r)-7(e)-4(ssive)-4( t)18(a)-4(x p)-4(o)-4(licie)-4(s th)16(a)-4(n)-4( o)-4(t)-2(h)16(e)-4(r)-7(s)0(, )20(m)-7(o)-4(b)-4(ility )-20(will )-20(le)-4(a)-4(d)]TJ
+T*
+0.004 Tc
+0.178 Tw
+[(ri)6(cher )20(p)20(eopl)6(e )20(to)20( move )20(out an)20(d poo)20(rer )20(peopl)6(e )20(to mov)24(e)0( i)6(n)0(. M)17(o)0(re )20(prog)20(ressi)6(ve)]TJ
+T*
+0.198 Tw
+[(pol)6(i)6(c)4(i)6(e)0(s are )20(onl)6(y possi)6(bl)6(e w)26(here )20(ri)6(cher)17( peopl)6(e)20( have )20(a pref)22(erenc)24(e )-20(for)17( )-20(i)6(t, )-20(and)]TJ
+T*
+0.002 Tc
+0.04 Tw
+[(ther)-5(e )20(is lim)-5(it)20(ed inwar)15(d)-2( m)-5(o)18(bility of poo)18(r)-5( pe)18(ople. New Y)9(o)-2(r)-5(k)22( City in the )20(1970s )20(and)]TJ
+0 -1.14 TD
+0.359 Tw
+[(1980s i)5(s)3( oft)21(en ci)5(ted )20(as a )-20(case)19( )-20(w)5(here prog)19(ressi)5(vi)5(ty )-20(fai)5(l)5(e)19(d. )-20( )-20(P)10(oor peopl)5(e)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(respond)19(ed to )20(gener)16(ous w)5(e)-1(l)5(f)1(a)19(r)-4(e by )20(movi)5(ng i)5(n)-1(,)21( and c)23(o)-1(rpo)19(r)-4(ati)5(ons )20(moved )20(out to the)]TJ
+T*
+0.159 Tw
+[(suburbs. )20(If i)5(n)-1( so)19(me ar)16(eas, th)19(e R)5(M)-4(A)10( provi)25(des publ)5(i)5(c)3( )20(goods )20(hi)5(ghl)5(y val)5(u)-1(e)19(d)-1( by)]TJ
+T*
+0.004 Tc
+0.318 Tw
+[(poore)20(r)-3( peopl)26(e at th)20(e expe)20(nse of )20(ri)6(cher )20(peopl)6(e, i)6(t)22( )-20(coul)6(d )-20(i)6(n)20(duce )-20(th)20(e )-20(same)]TJ
+T*
+[(phenom)17(enon.)]TJ
+0 -2.3 TD
+0.002 Tc
+0.14 Tw
+[(If T)-7(i)4(ebou)18(t-)-5(type)18( m)-5(obility p)18(r)-5(essu)18(r)-5(e)-2(s m)-5(a)-2(k)22(e)-2( com)15(m)-5(unities )20(r)-5(e)-2(latively h)18(o)-2(m)-5(o)-2(g)18(eneous)22(,)]TJ
+0 -1.16 TD
+0.004 Tc
+0.178 Tw
+[(seri)6(ous )20(r)17(edi)6(stri)6(bu)20(ti)6(on )20(re)20(qui)6(res i)26(n)0(ter)17(-)-3(j)6(u)0(ri)6(sdi)6(c)4(ti)6(ona)20(l)6( tra)20(n)0(sfers. )20( In the)20( absenc)24(e of)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(strong al)5(t)21(r)-4(ui)5(sm )20(by ri)5(che)19(r)-4( com)16(m)-4(uni)5(ti)5(es, )20(thi)5(s)3( requ)19(i)5(r)-4(es ce)19(ntral)5( c)23(oerci)5(on)19(.)]TJ
+0 -2.3 TD
+0.004 Tc
+0.038 Tw
+[(E)11(v)4(en )20(w)6(here )20(tax)24(e)0(s ar)17(e rai)6(s)4(e)20(d)0( i)6(n)0( ri)6(che)20(r)-3( co)20(mmuni)6(ti)6(es )20(to fi)6(na)20(nce i)6(n)0(tr)17(a-j)6(u)0(ri)6(s)24(d)0(i)6(c)4(ti)6(onal)]TJ
+0 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(r)-6(edistr)-6(i)3(bu)17(tion, if this is )20(not n)17(a)-3(tion wide, )20(m)-6(obility will lead )20(to capit)19(a)-3(lisation of these)]TJ
+T*
+0.003 Tc
+0.059 Tw
+[(tax i)5(n)-1(crease)19(s)3( and l)5(o)-1(w)25(e)-1(r p)19(r)-4(ope)19(rty val)5(ues i)5(n)19( the hi)5(g)19(her )-20(t)21(a)-1(x )-20(ar)16(eas. )-20( )-20(C)5(api)5(t)21(a)-1(l)5(i)5(s)3(ati)5(o)-1(n)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(ul)6(ti)6(matel)6(y)4( de)20(feats th)20(e redi)6(s)24(t)2(ri)6(buti)6(v)4(e )20(goal)6(.)]TJ
+0 -2.3 TD
+0.003 Tc
+0.099 Tw
+[(On )20(the ot)21(her h)19(and so)19(me evi)5(d)19(ence sug)19(gests tha)19(t)1( smal)5(l)5(e)19(r com)16(m)-4(uni)5(ti)5(es t)21(hat a)19(r)-4(e)]TJ
+0 -1.16 TD
+0.004 Tc
+0.198 Tw
+[(more h)20(o)0(mog)20(eneous)24( on no)20(n-i)6(n)0(co)20(me g)20(r)-3(ounds,)22( e.g.: )20(race )20(or r)17(e)0(l)6(i)6(g)0(i)6(on, )-20(m)17(a)0(y )-20(be)]TJ
+T*
+-0.001 Tc
+0.243 Tw
+[(m)-8(o)-5(r)-8(e)-5( willin)-5(g)-5( t)17(o)-5( r)-8(e)-5(d)-5(i)1(st)17(r)-8(i)1(b)-5(u)-5(t)-3(e)15( in)-5(co)-5(m)-8(e)-5( wit)17(h)-5(i)1(n)-5( th)-5(e)-5( co)15(m)-8(m)12(u)-5(n)-5(i)1(ty. )-20(Altr)-8(u)-5(i)1(s)19(m)-8( )-20(is )-20(m)-8(o)15(r)-8(e)]TJ
+T*
+0.004 Tc
+0.078 Tw
+[(preval)6(ent )40(tow)6(a)0(rd)20( )20(si)6(mi)6(l)6(a)0(r )20(peopl)6(e, )20(and w)6(h)0(e)20(r)-3(e the)20( effects)24( are )20(mor)17(e)0( vi)6(si)6(bl)6(e. Loc)24(al)]TJ
+T*
+0.003 Tc
+0.139 Tw
+[(redi)5(stri)5(bu)19(ti)5(on of t)21(h)-1(i)5(s)3( natu)19(r)-4(e m)16(a)-1(y avoi)5(d s)23(o)-1(me )-20(o)19(f)1( )-20(the )-20(e)19(ffi)5(ci)5(ency, )-20(i)5(n)-1(f)21(o)-1(rma)19(ti)5(on )-20(\(o)19(n)]TJ
+0 -1.14 TD
+0.004 Tc
+0.018 Tw
+[(w)6(ho )20(i)6(s)4( )20(real)6(l)6(y)4( )20(n)20(eedy an)20(d w)6(hat t)22(hey nee)20(d\), a)20(nd enf)22(orce)20(ment p)20(r)-3(obl)6(e)20(m)-3(s i)6(nhe)20(rent i)6(n)]TJ
+0 -1.16 TD
+0.003 Tc
+0.259 Tw
+[(nati)5(onal)5( r)16(edi)5(stri)5(bu)19(ti)5(on p)19(r)-4(ogr)16(ams. B)10(u)-1(si)5(ness)23(e)-1(s i)5(n)-1( smal)5(l)5( c)23(o)-1(mmu)19(ni)5(ti)5(es may)23( )-20(be)]TJ
+T*
+0.36 Tw
+[(willing )20(to )20(com)-5(p)-2(ly )20(with )20(s)22(t)0(r)-5(i)4(ct envi)24(r)-5(onm)15(ental sta)18(ndar)15(ds to b)18(enefit t)20(heir)-5( local)]TJ
+T*
+-0.001 Tc
+0.083 Tw
+[(co)-5(m)-8(m)-8(u)-5(n)-5(i)1(ty,)17( wh)-5(e)-5(r)-8(e)15( th)-5(e)-5(y)-1( a)15(r)-8(e)-5( u)-5(n)-5(willin)-5(g)-5( )20(to)-5( m)-8(a)-5(k)19(e)-5( )-20(sim)-8(ila)-5(r)-8( )-20(s)19(a)-5(cr)-8(ifice)-5(s)-1( )-20(f)17(o)-5(r)-8( )-20(th)15(e)-5( )-20(n)-5(a)-5(t)-3(io)-5(n)15(a)-5(l)]TJ
+T*
+0.004 Tc
+(good.)Tj
+0 -2.3 TD
+0.003 Tc
+0.079 Tw
+[(In the con)19(t)1(ext of t)21(he R)5(M)-4(A)10(,)1( th)19(e peo)19(pl)5(e w)5(ho )-20(l)5(o)-1(se)19( )-20(are those )-20(w)5(h)19(ose )-20(acti)5(vi)5(ti)5(es are)]TJ
+0 -1.16 TD
+0.219 Tw
+[(restri)5(cted)19( mor)16(e)-1( than)19( they val)25(ue the )20(avera)19(ge )-20(be)19(nefi)5(t)1(s )-20(fr)16(om )-20(th)19(e )-20(publ)5(i)5(c)3( )-20(g)19(oods)]TJ
+T*
+0.004 Tc
+0.158 Tw
+[(created. )20( S)11(o)0(me l)6(i)6(t)2(e)20(r)-3(atur)17(e sugg)20(ests that)22( commo)20(n res)24(ources)24( and )-20(p)20(ubl)6(i)6(c)4( )-20(goo)20(ds)]TJ
+ET
+endstream endobj 291 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 292 0 obj << /Type /Page /Parent 278 0 R /Resources 294 0 R /Contents 293 0 R >> endobj 293 0 obj << /Length 4091 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(66)Tj
+-34.32 58.88 TD
+0.003 Tc
+0.059 Tw
+[(di)5(spropo)19(rti)5(onat)21(el)5(y )20(benefi)5(t)21( )20(poo)19(rer )20(p)19(eopl)5(e )20(w)5(h)19(o have l)25(e)-1(ss access to)19( substi)5(tut)21(e)-1(s.)]TJ
+10.08 0 0 10.08 513.6 747.805 Tm
+-0.008 Tc
+(28)Tj
+12 0 0 12 99.36 730.88 Tm
+0.004 Tc
+0.298 Tw
+[(Thus they)24( may b)20(enefi)6(t)2( f)22(r)-3(om )20(the R)6(M)-3(A)11( m)17(o)0(re )-20(t)22(han )-20(hi)6(g)20(h)0(-i)6(nco)20(m)-3(e )-20(pe)20(opl)6(e. )-20( )-20(In)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(addi)5(ti)5(on, )20(i)5(n)-1( )40(a )20(tra)19(n)-1(spare)19(n)-1(t )20(setti)5(n)19(g)-1(, pol)5(i)5(t)1(i)5(c)3(al)5( p)19(r)-4(ocesses)23( tend t)21(o)-1( l)5(ead )20(to i)5(n)-1(cre)19(a)-1(sed)]TJ
+0 -1.14 TD
+[(progr)16(essi)5(vi)5(ty. W)7(hen b)19(enefi)5(t)1(s )20(and costs )20(are )20(non-t)21(r)-4(ansp)19(a)-1(rent)21(, pol)5(i)5(c)3(i)5(e)-1(s )-20(m)16(a)-1(y )-20(not)]TJ
+0 -1.16 TD
+-0.001 Tw
+[(be prog)19(ressi)5(ve.)]TJ
+0 -2.32 TD
+0.004 Tc
+0.178 Tw
+[(S)11(o)0(me )20(argu)20(e )20(that)22( poor)17(er p)20(eopl)6(e b)20(enefi)6(t)2( l)6(e)0(ss,)22( becaus)24(e envi)6(r)17(onme)20(n)0(tal)6( ben)20(efi)6(t)2(s)]TJ
+0 -1.16 TD
+0.003 Tc
+0.119 Tw
+[(are ofte)19(n l)5(u)-1(xury)23( goods.)21( )-20(If )-20(new)5( housi)5(ng devel)5(op)19(ments are )-20(p)19(r)-4(i)5(m)-4(a)19(r)-4(i)5(l)5(y)3( )-20(suppl)5(yi)5(ng)]TJ
+0 -1.14 TD
+0.004 Tc
+0.418 Tw
+[(poore)20(r)-3( peopl)26(e, the i)6(n)0(c)24(r)-3(ease)20(d)0( pri)6(c)4(es)24( of new)6( )20(houses )20(resul)6(t)2(i)6(ng )20(fro)20(m)-3( R)6(M)-3(A)]TJ
+0 -1.16 TD
+0.003 Tc
+0.259 Tw
+[(constrai)5(nts )20(on l)5(and)19( use an)19(d subdi)5(vi)5(si)5(o)19(n)-1( desi)5(gn,)21( are )20(heavi)5(l)5(y)3( )-20(bo)19(rne )-20(by)23( )-20(non-)]TJ
+0 -1.26 TD
+0.004 Tc
+0.118 Tw
+[(homeow)6(ne)20(rs w)6(ho t)22(end to)20( be p)20(oor.)]TJ
+10.08 0 0 10.08 288 607.885 Tm
+-0.008 Tc
+(29)Tj
+12 0 0 12 299.04 604.88 Tm
+0.004 Tc
+[( N)6(on-ho)20(meow)6(n)20(e)0(rs )-20(al)6(so mi)6(ss )-20(out on )-20(any)]TJ
+-16.64 -1.14 TD
+0.038 Tw
+[(benefi)6(t)2(s fr)17(om R)6(M)-3(A)11( w)6(h)0(i)6(c)4(h )20(are c)24(api)6(tal)6(i)6(s)4(ed i)6(n)20(to hous)24(e pri)6(c)4(es)24(. On )-20(th)20(e )-20(othe)20(r )-20(ha)20(nd,)]TJ
+0 -1.16 TD
+0.003 Tc
+0.179 Tw
+[(the costs of )20(many R)25(M)-4(A)10( constrai)25(nts are)19( al)5(so capi)5(t)21(a)-1(l)5(i)5(s)3(ed i)5(n)-1(to )20(the p)19(r)-4(i)5(c)3(e of )-20(t)21(h)-1(e)]TJ
+T*
+0.579 Tw
+[(l)5(and, )20(and )40(thus )20(aff)21(e)-1(ct )20(cur)16(r)-4(ent l)25(andow)5(ne)19(rs w)5(ho te)19(nd to)19( be be)19(tter )20(off.)]TJ
+T*
+0.004 Tc
+0.418 Tw
+[(H)6(o)0(meow)6(ne)20(rs )20(bea)20(r )20(costs a)20(nd re)20(al)6(i)6(s)4(e ben)20(efi)6(t)2(s at th)20(e poi)6(nt)22( i)6(n)0( ti)6(me w)26(hen)]TJ
+T*
+0.003 Tc
+0.299 Tw
+[(unanti)5(c)3(i)5(pate)19(d)-1( )20(chan)19(ges )20(i)5(n)-1( )20(th)19(e net v)23(a)-1(l)5(ue of )20(publ)5(i)5(c)3( go)19(ods ar)16(e anno)19(unced )20(or)]TJ
+0 -1.14 TD
+0.004 Tc
+0.218 Tw
+[(observed.)22( Th)20(e verti)6(c)4(al)6( )20(equi)6(ty b)20(a)0(l)6(ance d)20(epends)24( on th)20(e natu)20(r)-3(e of )20(the pu)20(bl)6(i)6(c)]TJ
+0 -1.16 TD
+0.003 Tc
+0.179 Tw
+[(goods pr)16(ovi)5(ded, )20(and h)19(ence w)5(h)-1(o)19(m)-4( they benefi)5(t)1(,)21( )-20(and )-20(t)21(he )-20(net)21( )-20(effect on )-20(hous)23(e)]TJ
+T*
+-0.001 Tw
+[(pri)5(c)3(es. T)14(h)-1(i)5(s)3( i)5(s)3( an e)19(m)-4(pi)5(ri)5(cal)5( )20(questi)5(on.)]TJ
+0 -30.46 TD
+0 Tw
+( )Tj
+ET
+0 0 0 RG
+0 J 1 j 0.72 w 10 M []0 d
+1 i
+200.166 132.56 m
+99.366 132.56 l
+S
+BT
+12 0 0 12 200.16 128.48 Tm
+( )Tj
+ET
+243.843 132.56 m
+200.163 132.56 l
+S
+BT
+10.08 0 0 10.08 99.36 116.845 Tm
+-0.008 Tc
+(28)Tj
+1.0952 -0.3095 TD
+0.015 Tw
+[( )-1429(Ref)-16(er)-8(enc)-8(e f)-16(r)-8(om)-8( Rim)-8(jhim)-8( or)15( M)-8(algos)-8(ia.)]TJ
+-1.0952 -2.2857 TD
+(29)Tj
+1.0952 -0.3095 TD
+1.444 Tw
+[( O)-16(wen )1429(M)-8(c)-8( )1452(S)-8(hane )1428(\()-8(1996\))]TJ
+ET
+endstream endobj 294 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 295 0 obj << /Length 6748 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(67)Tj
+/F3 1 Tf
+-34.32 58.94 TD
+-0.003 Tc
+[(REF)-12(E)4(RENCE)-16(S)]TJ
+/F5 1 Tf
+0 -2.16 TD
+0.004 Tc
+0.298 Tw
+[(A)11(l)6(esi)6(na, )20(A)11(l)6(berto )20(an)20(d )20(E)11(n)0(ri)6(co )20(S)11(pol)6(a)20(o)0(re )40(\(1995)20(\) \223On)20( the N)6(u)20(mber)17( and S)11(i)6(ze of)]TJ
+2.36 -1.14 TD
+0.003 Tc
+0.079 Tw
+[(N)5(a)-1(ti)5(ons\224 )20(N)5(a)-1(ti)5(o)19(nal)5( )20(B)10(u)-1(rea)19(u)-1( )20(of E)10(c)3(ono)19(mi)5(c R)5(e)-1(sea)19(r)-4(ch, Inc.)21( W)7(o)-1(rki)5(ng P)10(a)-1(p)19(e)-1(r N)5(o)-1(.)]TJ
+0 -1.16 TD
+0.004 Tc
+(5050)Tj
+-2.36 -2.32 TD
+-0.001 Tc
+0.363 Tw
+[(Ba)-5(u)-5(m)-8(o)-5(l)1(, )20(Willia)-5(m)-8( )20(a)-5(n)-5(d)15( Wa)-5(lla)-5(ce)-5( Oa)-5(te)-5(s)19( \()-8(1)-5(9)15(7)-5(5)-5(\))-8( )]TJ
+12 0 2.551 12 356.88 664.16 Tm
+0.004 Tc
+0.358 Tw
+[(The )20(Theo)20(ry of E)11(n)0(vi)6(ro)20(nmen)20(tal)]TJ
+-18.8534 -1.16 TD
+-0.004 Tc
+[(Po)-8(licy)]TJ
+12 0 0 12 159.6 650.24 Tm
+0.002 Tc
+0.14 Tw
+(: )Tj
+12 0 2.551 12 173.04 650.24 Tm
+[(E)10(x)3(ternal)5(i)5(t)1(i)5(e)-1(s, pu)19(bl)5(i)5(c)3( outl)5(a)-1(ys a)19(nd the)19( qual)5(i)5(t)1(y of)21( )-20(l)5(i)5(f)1(e)]TJ
+12 0 0 12 443.28 650.24 Tm
+-0.002 Tc
+0.164 Tw
+[( \()-9(P)5(r)-9(e)14(n)-6(t)-4(ice)-6(-)-9(Ha)-6(ll,)]TJ
+-26.3 -1.14 TD
+0.002 Tc
+0 Tw
+[(Inc. E)9(nglewood Cliffs, N)24(e)-2(w Jer)-5(s)2(ey)22(\))]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.198 Tw
+[(B)11(e)0(rgstrom)17(,)2( T., )20(L. B)11(l)6(ume a)20(nd H)6(.)2( V)11(a)0(ri)6(a)20(n)0(, )-20(\(1)20(986\) \223On )-20(t)22(he )-20(P)11(r)-3(i)6(v)4(ate )-20(P)11(r)17(ovi)6(s)4(i)6(on )-20(of)]TJ
+3 -1.16 TD
+-0.002 Tw
+[(P)11(ubl)6(i)6(c)4( Goods\224 )]TJ
+12 0 2.551 12 217.68 594.8 Tm
+[(Jo)20(urnal)6( )20(of P)11(ubl)6(i)6(c)4( E)11(c)4(onomi)6(c)4(s)]TJ
+12 0 0 12 368.4 594.8 Tm
+[(,)22( pp:25)20(-49)]TJ
+-22.42 -2.3 TD
+0.058 Tw
+[(C)6(oase, R)6(.)2( \(1)20(960\))17(\223Th)20(e)0( P)11(r)-3(obl)6(e)20(m)-3( of S)11(o)0(ci)6(al)6( C)6(o)0(st)22(\224 )]TJ
+12 0 2.551 12 357.36 567.2 Tm
+0.078 Tw
+[(Jou)20(r)-3(nal)6( of )20(Law)6( and)20( E)11(c)4(onomi)6(c)4(s)]TJ
+12 0 0 12 127.68 553.28 Tm
+(pp:1-44)Tj
+-2.36 -2.36 TD
+0.018 Tw
+[(C)6(ohen, )20(W)8(e)0(sl)6(ey )40(M. )20(and )20(R)6(i)6(c)4(h)20(a)0(rd C)6(.)2( )20(Levi)6(n)0( \()17(1989)20(\) \223E)11(mpi)26(r)-3(i)6(c)4(al)6( S)11(t)2(udi)6(es of )20(Innovati)26(o)0(n)]TJ
+3 -1.14 TD
+0.198 Tw
+[(and Ma)20(rket S)11(t)2(ruct)22(ure)20(\224)-3( i)6(n)0( )]TJ
+12 0 2.551 12 282.96 511.28 Tm
+0.003 Tc
+0.219 Tw
+[(H)5(a)-1(n)19(dbook )20(o)19(f)1( Indust)21(r)-4(i)5(a)-1(l)5( Or)16(gani)5(zati)5(o)19(n)]TJ
+12 0 0 12 481.92 511.28 Tm
+0.001 Tc
+0.221 Tw
+[(, V)8(o)-3(l. II)]TJ
+-28.88 -1.16 TD
+-0.001 Tc
+0.003 Tw
+[(e)-5(d)-5(s)-1(. R. Sch)-5(m)-8(a)-5(l)1(e)-5(n)-5(s)19(e)-5(e)-5( a)-5(n)15(d)-5( R. D. Willig)-5( \()-8(E)6(lse)-5(v)-1(ie)-5(r)-8( Scie)-5(n)-5(c)19(e)-5( Pu)-5(b)-5(lish)-5(e)-5(r)-8(s B.V.\))]TJ
+-3 -2.32 TD
+0.002 Tc
+0.54 Tw
+[(Dinan, T)-7(e)18(r)-5(r)-5(y)2( a)18(nd Natalie )20(T)-7(a)-2(wil \()-5(1)18(997\))-5(,)20( \223)-5(F)13(eder)-5(alis)22(m)-5( )-20(and)18( )-20(E)9(n)-2(vir)-5(onm)15(ental)]TJ
+2.36 -1.16 TD
+0.239 Tw
+[(P)10(r)-4(otecti)5(on: )20(C)5(a)-1(se)19( )20(S)10(t)1(udi)5(es fo)19(r D)5(r)-4(i)5(n)-1(ki)5(ng W)27(a)-1(ter an)19(d Gr)16(ound)19(-Level)5( Oz)23(one\224)]TJ
+0 -1.14 TD
+0 Tw
+[(U.S)9(.)0( Congressional B)9(u)18(dget Offic)22(e)-2(, Novem)15(ber)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.058 Tw
+[(D)6(o)0(rmer,)22( )20(A)11(l)6(an \(19)20(94\))17(\223The)20( R)6(e)0(sourc)24(e)0( Man)20(ageme)20(n)0(t A)11(c)4(t 19)20(91: T)15(he tr)17(ansi)6(t)2(i)6(on a)20(n)0(d)]TJ
+2.36 -1.16 TD
+0.178 Tw
+[(busi)6(ness\224 R)6(e)20(port )20(prep)20(ared )20(for th)20(e N)6(e)0(w)6( Z)15(eal)6(and )-20(B)11(u)0(si)6(n)20(e)0(ss )-20(R)6(ound)20(tabl)6(e.)]TJ
+T*
+0.003 Tc
+[(A)10(ugust)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+0.158 Tw
+[(E)11(p)0(stei)6(n, R)6(i)6(c)4(hard )20(\(199)20(0\) \223A)11(uckl)6(a)20(nd U)6(n)0(i)6(v)4(ersi)6(ty)24( S)11(e)0(mi)6(nar)17( )-20(on )-20(Law)6( and )-20(R)6(e)0(so)20(urce)]TJ
+2.36 -1.16 TD
+0.005 Tc
+-0.003 Tw
+[(Manage)21(ment)23(\224 24 J)25(u)1(l)7(y)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.318 Tw
+[(E)11(p)0(stei)6(n, R)6(i)6(c)4(hard A)11(.)2( \(1995)20(\) )-20( )]TJ
+12 0 2.551 12 266.88 316.88 Tm
+-0.002 Tc
+0.344 Tw
+[(Sim)-9(p)-6(le)-6( Ru)-6(l)20(e)-6(s fo)-6(r)-9( )20(a)-6( Co)-6(m)-9(p)-6(le)-6(x)18( Wo)-6(r)-9(l)0(d)]TJ
+12 0 0 12 470.64 316.88 Tm
+0.007 Tc
+0.335 Tw
+[( \(H)29(arv)7(a)23(rd)]TJ
+-28.58 -1.14 TD
+-0.001 Tc
+0.003 Tw
+[(Un)-5(ive)-5(r)-8(sity Pr)-8(e)-5(ss: Ca)15(m)-8(b)-5(r)-8(i)1(d)15(g)-5(e)-5(,)-3( M)-8(A)6(\))]TJ
+-2.36 -2.32 TD
+0.003 Tc
+0.399 Tw
+[(E)10(r)-4(nst and Y)10(oun)19(g \(19)19(97\) )20(\223C)5(ase S)10(t)1(udy A)10(ssessm)16(ent o)19(f)1( the )-20(I)21(m)-4(pact of )-20(the)]TJ
+2.36 -1.16 TD
+0.004 Tc
+0.298 Tw
+[(R)6(e)0(source )20(Manag)20(ement)22( A)11(c)4(t \(199)20(1\) on)20( B)11(u)0(si)6(ness\224 )20(Fi)6(nal)6( R)6(e)0(p)20(o)0(rt to)20( N)6(Z)]TJ
+T*
+0.003 Tc
+-0.001 Tw
+[(Mi)5(ni)5(stry of C)5(o)19(mme)19(rce, R)5(e)-1(so)19(urces )20(and N)5(e)-1(tw)5(o)19(r)-4(ks B)10(r)-4(anch)19(.)]TJ
+-2.36 -2.3 TD
+-0.001 Tc
+1.103 Tw
+[(F)-10(r)-8(ie)-5(d)-5(e)15(r)-8(,)-3( Ju)-5(lie)-5( )20(\223)-8(A)6(p)-5(p)-5(r)-8(o)-5(a)-5(c)19(h)-5(i)1(n)-5(g)-5( Su)-5(sta)-5(i)1(n)-5(a)15(b)-5(ility: In)-5(te)-5(g)15(r)-8(a)-5(t)-3(e)15(d)-5( )-20(En)-5(vir)-8(o)-5(n)15(m)-8(e)-5(n)-5(t)-3(a)-5(l)]TJ
+2.36 -1.16 TD
+0.002 Tc
+0.02 Tw
+[(M)-5(anage)18(m)-5(ent )20(and New )20(Z)-7(ealan)18(d\222s Resour)-5(c)22(e)-2( M)-5(a)18(nage)18(m)-5(ent A)9(c)2(t\224)-5(, )-20(Wellin)18(gton,)]TJ
+T*
+0.004 Tc
+-0.002 Tw
+[(N)6(.)2(Z.: Ian A)11(x)4(fo)20(rd N)6(e)0(w)6( )20(Zeal)6(an)20(d Fel)6(l)6(o)0(w)6(s)4(hi)26(p i)6(n)0( P)11(ubl)6(i)6(c)4( P)11(o)0(l)6(i)6(cy, 1997)20(.)]TJ
+-2.36 -2.3 TD
+0.003 Tc
+0.079 Tw
+[(Grew)5(al)5(, )20(B)10(haj)5(an )20(S)10(.)1( G)21(eoffr)16(ey B)10(r)-4(enna)19(n and R)25(u)-1(ssel)5( L. )20(Mathew)5(s e)19(d)-1(s. \(1)19(980\))16( )]TJ
+12 0 2.551 12 504 164.48 Tm
+0.009 Tc
+[(Th)25(e)]TJ
+-31.1134 -1.16 TD
+0.004 Tc
+0.398 Tw
+[(E)11(c)4(onomi)6(cs of )20(Feder)17(al)6(i)6(s)4(m)]TJ
+12 0 0 12 272.16 150.56 Tm
+0.418 Tw
+[( \(A)11(ust)22(r)-3(al)6(i)6(an N)6(a)0(ti)6(o)20(nal)6( U)6(n)0(i)6(v)4(ersi)6(ty)24(: C)6(anb)20(erra)20(,)]TJ
+-12.04 -1.16 TD
+-0.003 Tc
+[(Au)-7(str)-10(a)-7(lia)-7(\))]TJ
+-2.36 -2.32 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(a)0(rdi)6(n)0( \(1)20(968\))17( "Th)20(e)0( T)15(r)-3(agedy )20(of the C)26(o)0(mm)17(ons" )]TJ
+12 0 2.551 12 347.52 108.8 Tm
+0.003 Tc
+[(S)10(c)3(i)5(ence)]TJ
+12 0 0 12 390.24 108.8 Tm
+0.004 Tc
+[( )20(162: 1)20(243-1)20(248)]TJ
+ET
+endstream endobj 296 0 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 297 0 obj << /Type /Page /Parent 278 0 R /Resources 299 0 R /Contents 298 0 R >> endobj 298 0 obj << /Length 6821 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(68)Tj
+-34.32 58.98 TD
+0.138 Tw
+[(H)6(a)0(rtl)6(e)0(y, P)11(e)0(ter)17( )-20(\(199)20(7\) )]TJ
+12 0 2.551 12 219.84 746 Tm
+0.158 Tw
+[(C)6(ons)24(ervati)6(o)20(n)0( S)11(t)2(rate)20(gi)6(es for)17( N)6(e)0(w)6( Ze)20(al)6(and)]TJ
+12 0 0 12 446.88 746 Tm
+0.005 Tc
+0.157 Tw
+[( N)7(e)1(w)7( )20(Zeal)7(an)21(d)]TJ
+-26.6 -1.16 TD
+0.002 Tc
+0 Tw
+[(B)9(u)-2(si)4(ness R)4(oundta)18(b)-2(l)4(e)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.458 Tw
+[(K)11(a)0(rshenas, )20(Massoud)20( and P)11(aul)6( S)11(t)2(on)20(eman)20( )-20(\(199)20(5\)\223T)15(ech)20(nol)6(ogi)6(cal)6( )-20(D)6(i)6(ffusi)6(o)20(n)0(\224)]TJ
+12 0 2.551 12 135.36 690.56 Tm
+0.003 Tc
+-0.001 Tw
+[(H)5(andbook o)19(f)1( the E)10(c)3(on)19(omi)5(cs of I)21(nnovati)5(o)19(n )-20(and Tech)19(nol)5(ogi)5(cal)5( )-20(C)5(h)19(ange)]TJ
+12 0 0 12 504.48 690.56 Tm
+-0.016 Tc
+0.038 Tw
+[( ed)-20(.)]TJ
+-30.76 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(P)11(aul)6( S)11(t)2(oneman )20(\(B)11(asi)6(l)6( B)11(l)6(ackw)6(el)6(l)6( Ltd.: Oxf)22(o)0(rd\))17( pp.2)20(65 - 2)20(9)0(7)]TJ
+-3 -2.32 TD
+0.098 Tw
+[(McS)11(hane, )20(Ow)6(en)20( \(19)20(96\) )20(\223The)20( i)6(m)-3(pact )20(of the R)26(e)0(sourc)24(e)0( Man)20(agem)17(ent A)11(c)4(t on t)22(h)0(e)]TJ
+2.36 -1.16 TD
+0.003 Tc
+0.219 Tw
+[(\223housi)5(ng )20(and co)19(nstructi)5(o)19(n)-1(\224 co)19(mpon)19(ents of t)21(he C)5(ons)23(umer)16( P)10(r)-4(i)5(c)3(e )-20(Index)23(\224)]TJ
+0 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(R)6(eport p)20(r)-3(epa)20(red fo)20(r the R)26(e)0(serve B)11(a)20(nk of N)6(e)0(w)6( )20(Zeal)6(an)20(d)]TJ
+-2.36 -2.32 TD
+[(Mi)6(ni)6(stry fo)20(r the E)11(n)0(vi)6(r)17(onme)20(n)0(t \(1)20(991\) )]TJ
+12 0 2.551 12 290.16 593.36 Tm
+0.005 Tc
+[(Mana)21(gi)7(ng ou)21(r F)16(u)1(ture)]TJ
+12 0 0 12 99.36 565.52 Tm
+0.004 Tc
+[(Mi)6(ni)6(stry fo)20(r the E)11(n)0(vi)6(r)17(onme)20(n)0(t \(1)20(991\) )]TJ
+12 0 2.551 12 290.4 565.52 Tm
+0.003 Tc
+-0.001 Tw
+[(C)25(onsul)5(tati)5(o)19(n)-1( w)5(i)5(t)1(h T)14(angata)19( W)7(henua)]TJ
+12 0 0 12 99.36 537.92 Tm
+0.004 Tc
+0.198 Tw
+[(Mi)6(ni)6(stry fo)20(r the E)11(n)0(vi)6(r)17(onme)20(n)0(t )-20(\(1)20(993\) )]TJ
+12 0 2.551 12 302.88 537.92 Tm
+0.003 Tc
+0.219 Tw
+[(S)10(e)-1(cti)25(on 32 )20(- A)10( Gui)5(de t)21(o)-1( Good)19( P)10(r)-4(acti)5(ce)]TJ
+12 0 0 12 127.68 524 Tm
+0.004 Tc
+0.038 Tw
+[(prepa)20(red by A)11(d)20(ri)6(enne Y)11(o)0(u)20(ng-C)6(o)20(oper, B)11(e)0(l)6(l)6( G)22(u)0(l)6(l)6(y)4( )-20(B)11(uddl)6(e )-20(W)8(e)0(i)6(r)-3( \(Ian )-20(C)6(o)0(w)26(per)]TJ
+0 -1.16 TD
+0.002 Tc
+0 Tw
+[(and Rebecca)18( M)-5(a)-2(cky\))15( and D)24(r)-5( P)9(h)-2(ilip M)-5(c)2(Der)15(m)-5(ott)]TJ
+-2.36 -2.3 TD
+0.004 Tc
+0.018 Tw
+[(Mi)6(nstry )20(fo)20(r )20(the )20(E)11(n)0(vi)26(ronme)20(n)0(t, )20( \()17(1998)20(\) W)8(ebsi)6(t)2(e o)20(n)0( the R)26(e)0(source)20( Man)20(agem)17(ent A)11(c)4(t)]TJ
+2.36 -1.16 TD
+0.003 Tc
+-0.001 Tw
+[(and E)10(n)-1(vir)-4(o)-1(n)19(m)-4(ent 2)19(010 S)10(t)1(r)-4(a)19(tegy htt)21(p)-1(://www.m)-4(f)1(e)19(.)1(govt.nz)23(/)1(2010.)21(htm)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.338 Tw
+[(Myerson,)22( R)6(.)2( B)11(.)2( and )20(M. A)11(.)2( S)11(a)0(ttert)22(hw)6(ai)6(te )-20(\()17(1983)20(\) )-20(\223E)11(ffi)6(ci)6(ent mechani)6(s)24(m)-3(s )-20(for)]TJ
+2.36 -1.16 TD
+0.005 Tc
+-0.003 Tw
+[(bi)7(l)7(a)1(teral)7( t)23(r)-2(adi)7(ng)21(\224 )]TJ
+12 0 2.551 12 220.56 426.8 Tm
+0.004 Tc
+[(Jou)20(r)-3(nal)6( of E)11(c)4(on)20(omi)6(c)4( )20(Theory)]TJ
+12 0 0 12 369.84 426.8 Tm
+[( 28: )20(265 - )20(281)]TJ
+-22.54 -2.3 TD
+0.002 Tc
+0.44 Tw
+[(New )20(Z)-7(ealan)18(d )20(B)9(u)-2(siness Roun)18(dtable )20(\()-5(199)18(0\))-5( \223)-5(R)4(e)18(s)2(our)-5(c)22(e)-2( M)-5(a)-2(n)18(agem)15(ent B)9(ill:)]TJ
+2.36 -1.16 TD
+0.099 Tw
+[(S)10(ubmi)5(ssi)5(on to th)19(e S)10(e)-1(l)5(e)-1(ct C)5(o)-1(m)16(m)-4(i)5(ttee )20(of the H)25(ouse of R)25(epres)23(entati)5(v)3(es )20(on)]TJ
+T*
+0 Tw
+[(the Resour)-5(c)22(e)-2( M)-5(a)18(nage)18(m)-5(ent B)9(ill\224)-5( M)15(a)-2(r)-5(c)2(h.)]TJ
+-2.36 -2.3 TD
+0.179 Tw
+[(Ol)5(son, M. J)23(r)-4(. \(1)19(980\), )20(\223Th)19(e)-1( P)10(r)-4(i)5(n)-1(ci)5(pl)5(e o)19(f)1( \221)5(F)-6(i)5(scal)5( )-20(E)10(qui)5(val)5(e)19(nce\222)5(: )-20( )-20(T)14(he )-20(D)5(i)5(v)3(i)5(s)3(i)5(on )-20(of)]TJ
+2.36 -1.16 TD
+0.42 Tw
+[(Responsibilities )20(am)15(ong )20(Diffe)18(r)-5(ent )40(Levels )20(of G)20(o)-2(ver)-5(n)18(m)-5(ent)20(\224)-5( in G)20(r)-5(ewal,)]TJ
+T*
+0.059 Tw
+[(B)10(haj)5(an )20(S)10(.)1( )20(Geoffr)16(ey B)10(r)-4(enn)19(an and)19( R)5(u)-1(ssel)5( L. )20(Mathew)5(s )20(eds. )]TJ
+12 0 2.551 12 441.36 315.92 Tm
+0.004 Tc
+0.058 Tw
+[(T)15(he E)11(c)4(ono)20(mi)6(cs)]TJ
+-25.8934 -1.16 TD
+0.005 Tc
+0.037 Tw
+[(of Fede)21(ral)7(i)7(s)5(m)]TJ
+12 0 0 12 201.12 302 Tm
+0.003 Tc
+0.059 Tw
+[( )40(\(A)10(ustral)5(i)5(a)-1(n)19( N)5(a)-1(ti)5(onal)5( U)5(n)-1(i)5(v)3(e)19(r)-4(si)5(ty: C)5(a)-1(n)19(ber)16(ra, A)10(u)-1(stral)5(i)25(a\) pp.)21( 25)]TJ
+-6.12 -1.16 TD
+0.006 Tc
+-0.004 Tw
+(- 38)Tj
+-2.36 -2.3 TD
+0.004 Tc
+0.078 Tw
+[(Oates, W)8(a)0(l)6(l)6(a)0(ce )20(\(1998)20(\) \223)17(T)-5(hi)6(nki)6(ng about )-20(E)11(n)0(vi)6(r)17(onme)20(n)0(tal)6( )-20(F)15(eder)17(al)6(i)6(s)4(m\224 )-20( )]TJ
+12 0 2.551 12 467.28 260.48 Tm
+[(R)6(e)0(s)24(ources)]TJ
+12 0 0 12 127.68 246.56 Tm
+0.003 Tc
+-0.001 Tw
+[(Issue 130 W)7(i)5(nt)21(er)]TJ
+-2.36 -2.32 TD
+0.819 Tw
+[(Oates, )20(W)7(a)-1(l)5(l)5(a)-1(ce "E)10(nvi)25(r)-4(onm)16(ental)5( P)10(o)-1(l)5(i)5(cy i)5(n)-1( th)19(e E)10(u)-1(rope)19(an C)5(o)-1(m)16(m)-4(uni)5(ty:)]TJ
+2.36 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(H)6(a)0(rmoni)6(zati)26(on or)17( N)6(a)0(ti)6(onal)6( S)11(t)2(an)20(dards)24(?" E)11(m)-3(pi)6(ri)6(c)24(a)0(, for)17(t)2(hcomi)6(n)20(g)]TJ
+-2.36 -2.32 TD
+0.003 Tc
+0.119 Tw
+[(Ostrom, E)10(lino)19(r)-4( \(19)19(90\) )]TJ
+12 0 2.551 12 222.24 177.2 Tm
+0.004 Tc
+0.138 Tw
+[(G)22(o)0(verni)6(n)20(g the C)26(o)0(mmo)20(ns: T)15(he E)11(v)4(ol)6(uti)6(on )20(of Insti)6(t)2(u)20(t)2(i)6(ons)]TJ
+-6.9934 -1.16 TD
+-0.001 Tc
+0.003 Tw
+[(fo)-5(r)-8( Co)-5(lle)-5(ctive)-5( Actio)-5(n)]TJ
+12 0 0 12 241.68 163.28 Tm
+0.004 Tc
+-0.002 Tw
+[( )20(\(C)6(amb)20(r)-3(i)6(dge U)6(n)0(i)6(v)24(ersi)6(ty P)11(r)-3(ess)24(\))]TJ
+-11.86 -2.3 TD
+0.002 Tc
+0.36 Tw
+[(P)9(a)-2(lm)-5(er)-5(, Geo)18(ffr)-5(ey )20(\()-5(1990)18(\))-5(,)0( \223)15(T)-7(he Res)22(our)-5(ce)18( M)-5(ana)18(gem)-5(e)18(n)-2(t B)9(ill\224)-5(, )]TJ
+12 0 2.551 12 447.84 135.68 Tm
+[(E)10(n)-1(vi)5(ron)19(m)-4(ental)]TJ
+-26.4334 -1.16 TD
+0.004 Tc
+0.198 Tw
+[(P)11(o)0(l)6(i)6(t)2(i)6(cs: A)11( Greenpri)6(n)20(t for N)26(e)0(w)6( Zeal)26(and)]TJ
+12 0 0 12 349.68 121.76 Tm
+0.218 Tw
+[( )20(\(J)24(ohn Mc)24(Indoe)20(: D)6(unedi)6(n)20(,)2( N)6(e)0(w)]TJ
+-18.5 -1.16 TD
+0.005 Tc
+[(Zeal)7(and)21(\))]TJ
+ET
+endstream endobj 299 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 300 0 obj << /Type /Page /Parent 278 0 R /Resources 302 0 R /Contents 301 0 R >> endobj 301 0 obj << /Length 6959 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 511.2 38.24 Tm
+0 0 0 rg
+0.004 Tc
+(69)Tj
+-34.32 58.98 TD
+0.098 Tw
+[(P)11(a)0(vl)6(eti)6(c)4(h, H)6(ugh J. a)20(nd Ow)6(en )20(McS)11(hane )20(\(199)20(7\) \223T)15(aki)6(ng the )-20(H)6(eat)22( )-20(off )-20(th)20(e )-20(R)6(M)-3(A)11(\224)]TJ
+2.36 -1.16 TD
+-0.002 Tw
+[(R)6(eport fo)20(r H)6(on. S)11(i)6(mo)20(n U)6(p)0(ton)20(,)2( Mi)6(ni)6(ste)20(r)-3( for)17( the E)11(n)0(vi)6(ro)20(nmen)20(t, N)6(e)0(w)6( Z)15(eal)6(and.)]TJ
+-2.36 -2.32 TD
+[(P)11(e)0(rmi)6(t data )20(fro)20(m)-3( C)6(ounci)6(l)6(s)4( \(s)24(ee Ow)6(en )20(McS)11(hane )20(\(199)20(6\)p. )20(15\))]TJ
+0 -2.3 TD
+[(P)11(aul)6( P)11(e)0(terson \()17(1995)20(\) )]TJ
+12 0 2.551 12 219.6 676.64 Tm
+0.005 Tc
+[(Th)21(e P)12(r)-2(i)7(c)5(e of )20(Fed)21(e)1(ral)7(i)7(s)5(m)]TJ
+12 0 0 12 347.04 676.64 Tm
+0.003 Tc
+-0.001 Tw
+[( B)10(r)16(ooki)5(ngs Ins)23(t)1(i)5(t)1(uti)5(o)-1(n)]TJ
+-20.64 -2.32 TD
+0.039 Tw
+[(P)10(o)-1(linsky, M. \223T)14(he Coase)19( T)-6(h)-1(e)19(o)-1(re)19(m\224 Cha)19(p)-1(ter )20(3 and \223F)-6(irs)23(t)1( )-20(A)10(pplication - )-20(Nuisance)]TJ
+3 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(Law)6(\224 C)6(hapt)22(er 4.)22( )]TJ
+12 0 2.551 12 227.52 634.88 Tm
+0.003 Tc
+-0.001 Tw
+[(Intr)16(oducti)5(on )20(to Law)5( a)19(nd E)10(c)3(ono)19(mi)5(cs)]TJ
+12 0 0 12 414.24 634.88 Tm
+0.004 Tc
+-0.002 Tw
+[( 1989)20( pp.14)20(4 - 1)20(5)0(3)]TJ
+-26.24 -2.3 TD
+[(P)11(u)0(tnam, R)6(obe)20(rt )]TJ
+12 0 2.551 12 186.96 607.28 Tm
+0 Tc
+0.002 Tw
+[(M)13(a)-4(kin)-4(g)-4( De)-4(m)13(o)-4(cr)-7(a)-4(cy Wo)16(r)-7(k)0(: Civic tr)-7(a)16(d)-4(itio)-4(n)-4(s)0( )-20(in)-4( m)-7(o)-4(d)-4(e)16(r)-7(n)-4( )-20(Ita)-4(ly)]TJ
+12 0 0 12 488.4 607.28 Tm
+0.004 Tc
+0.018 Tw
+[( R)6(o)20(ber)]TJ
+-30.06 -1.16 TD
+0.558 Tw
+[(P)11(u)0(tnam )20(w)6(i)6(t)2(h )20(R)6(o)0(b)20(e)0(rt L)20(eona)20(rdi)6( and R)26(a)0(ffael)6(l)6(a)0( Y)11( N)6(a)0(n)20(e)0(tti)6(. \(P)11(ri)6(nc)24(eton)]TJ
+T*
+0.002 Tc
+0 Tw
+[(U)4(n)-2(i)4(v)2(ersi)4(ty P)9(r)-5(ess, P)9(r)-5(i)4(n)-2(ce)18(ton, N)4(e)-2(w)4( Je)18(rsey 1)18(993\))]TJ
+-2.36 -2.3 TD
+0.004 Tc
+0.118 Tw
+[(R)6(e)0(i)6(nganum,)22( J. F. )20(\(198)20(9\) \223)17(T)-5(he )20(Ti)6(mi)6(ng)20( of Inn)20(o)0(vati)6(on:)22( R)6(e)0(searc)24(h)0(, D)6(e)0(vel)6(o)20(pment)22(,)]TJ
+3 -1.16 TD
+[(and D)6(i)6(ffusi)6(on)20(\224 )-20( )]TJ
+12 0 2.551 12 221.04 537.92 Tm
+0.003 Tc
+0.139 Tw
+[(H)5(and)19(book of )20(Indust)21(r)-4(i)5(a)-1(l)5( Org)19(ani)5(zati)5(on)]TJ
+12 0 0 12 417.6 537.92 Tm
+[(,)20( V)9(o)-2(lume I )20(eds. R.)]TJ
+-23.52 -1.16 TD
+-0.002 Tc
+0.004 Tw
+[(Sch)-6(m)-9(a)-6(l)0(e)-6(n)-6(s)-2(e)-6(e)-6( a)14(n)-6(d)-6( R. D. Willig)-6( \()-9(E)5(lse)-6(v)-2(ie)14(r)-9( Scie)-6(n)-6(c)-2(e)-6( Pu)-6(b)-6(lish)-6(e)14(r)-9(s)-2( B.V.\))]TJ
+-3 -2.32 TD
+0.002 Tc
+0.08 Tw
+[(Rondinelli, Dennis A)9(.)0( \()15(1990)18(\))-5( Decent)20(r)-5(a)-2(lising Ur)15(ban Dev)22(e)-2(lopm)-5(e)18(n)-2(t P)9(r)-5(og)18(r)-5(a)-2(m)-5(s)2(: )20( )-20(A)]TJ
+12 0 2.551 12 127.68 482.48 Tm
+0.004 Tc
+-0.002 Tw
+[(Fram)17(ew)6(ork fo)20(r A)11(nal)6(ysi)6(ng )-20(P)11(o)0(l)6(i)6(c)4(y)]TJ
+12 0 0 12 296.16 482.48 Tm
+0.003 Tc
+0.019 Tw
+[( U)5(S)10( A)10(gency for)16( Inte)19(rnati)5(o)19(nal)5( D)5(e)-1(vel)5(o)19(pment,)]TJ
+-14.04 -1.16 TD
+-0.001 Tw
+[(W)7(a)-1(shi)5(ngton D)5(C)]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.178 Tw
+[(R)6(ubi)6(nfel)6(d, D)6(ani)6(el)6( )20(L. \(1)20(987\))17( \223T)15(he E)11(c)4(ono)20(mi)6(cs of )-20(the)20( )-20(Local)6( )-20(P)11(ubl)6(i)6(c)4( )-20(S)11(e)0(cto)20(r\224 )-20( )-20(i)6(n)]TJ
+2.36 -1.16 TD
+0.038 Tw
+[(A)11(uerbach, A)11(.)2( J. )20(and M.)22( Fel)6(d)0(st)22(ei)6(n eds. )]TJ
+12 0 2.551 12 334.8 426.8 Tm
+0.003 Tc
+[(H)25(andboo)19(k of P)10(ubl)5(i)5(c)3( E)10(c)3(ono)19(mi)5(cs)]TJ
+12 0 0 12 502.08 426.8 Tm
+0 Tc
+0.042 Tw
+[( vol.)]TJ
+-31.2 -1.14 TD
+0.004 Tc
+-0.002 Tw
+[(II \(E)11(l)6(s)4(evi)6(e)0(r S)11(c)4(i)6(ence P)11(ubl)6(i)6(s)4(h)20(e)0(rs B)11(.)2(V)11(.)2( :N)6(ort)22(h)0( H)6(o)0(l)6(l)6(and\))]TJ
+-2.36 -2.32 TD
+0.098 Tw
+[(S)11(a)0(l)6(m)-3(on, Guy )20(\(1991)20(\), \223R)6(es)24(ource )20(mana)20(geme)20(n)0(t l)6(egi)6(sl)6(ati)6(o)20(n i)6(n)0( N)6(e)0(w)6( Z)15(eal)6(and:)22( )-20(the)]TJ
+2.36 -1.16 TD
+0.238 Tw
+[(fi)6(rst )20(step )20(to)20( a gr)17(een ec)24(onomy)24(?)0(\224 i)6(n)0( )]TJ
+12 0 2.551 12 335.28 371.36 Tm
+0.002 Tc
+0.24 Tw
+[(E)9(n)-2(vir)15(onm)-5(en)18(tal Resou)18(r)-5(ces a)18(nd the)]TJ
+-17.0534 -1.16 TD
+0.006 Tc
+[(Mark)6(et)24(-P)13(l)8(a)2(c)6(e)]TJ
+12 0 0 12 198.48 357.44 Tm
+0.003 Tc
+0.019 Tw
+[( )20(Tas)23(m)-4(an )20(Ins)23(t)1(i)5(t)1(ute, )20(Marke)19(t)1(s and E)10(n)-1(vi)5(r)16(onme)19(n)-1(t P)10(r)-4(oj)5(ect,)21( \(A)10(l)5(l)5(en &)]TJ
+-5.9 -1.14 TD
+-0.001 Tc
+0.003 Tw
+[(Un)-5(win)-5(: Au)-5(str)-8(a)-5(lia)-5(\))]TJ
+-2.36 -2.32 TD
+0.004 Tc
+0.418 Tw
+[(S)11(a)0(muel)6(son, P)11(.)2( \()17(1955)20(\) \223D)6(i)6(a)0(g)20(r)-3(amm)17(a)0(ti)6(c E)11(x)4(posi)6(t)2(i)6(on o)20(f)2( the )20(Theo)20(ry of )-20(P)11(ubl)6(i)6(c)]TJ
+2.36 -1.16 TD
+0.005 Tc
+-0.003 Tw
+[(E)12(x)5(pendi)7(ture)21(\224 )]TJ
+12 0 2.551 12 202.56 302 Tm
+0.002 Tc
+0 Tw
+[(R)4(e)-2(vi)4(ew)4( of E)9(c)2(o)18(nomi)4(cs an)18(d S)9(t)0(ati)4(s)2(ti)4(cs)]TJ
+12 0 0 12 391.92 302 Tm
+0.004 Tc
+-0.002 Tw
+[(, pp)20(. 266)20(-279)]TJ
+-24.38 -2.3 TD
+0.158 Tw
+[(Ti)6(dema)20(nn )20(and)20( )20(Tul)6(l)6(o)0(ck )40(\(197)20(6\) )20(\223A)11( )20(new)6( )40(and su)20(peri)6(o)20(r pr)17(ocess for)17( maki)6(ng)20( soci)6(al)]TJ
+2.36 -1.16 TD
+0.001 Tc
+0.001 Tw
+[(choices\224)-6( )]TJ
+12 0 2.551 12 179.28 260.48 Tm
+0.004 Tc
+-0.002 Tw
+[(Jo)20(urnal)6( o)20(f)2( P)11(o)0(l)6(i)6(t)2(i)6(c)4(al)6( E)11(c)4(onomy)]TJ
+12 0 0 12 330 260.48 Tm
+[(, )20(84, 114)20(5-1)20(159)]TJ
+-19.22 -2.32 TD
+0.238 Tw
+[(Ti)6(ebout, C)26(harl)6(e)0(s )20(\(195)20(6\) \223A)11( P)11(u)0(r)17(e)0( The)20(o)0(ry of)22( Local)6( E)11(x)4(pen)20(di)6(tures)24(\224)-3( )-20( )]TJ
+12 0 2.551 12 468.96 232.64 Tm
+0.003 Tc
+0.259 Tw
+[(Jou)19(r)-4(nal)5( of)]TJ
+-28.1934 -1.16 TD
+0.004 Tc
+-0.002 Tw
+[(P)11(o)0(l)6(i)6(t)2(i)6(c)4(al)6( E)11(c)4(onomy)]TJ
+12 0 0 12 222.48 218.72 Tm
+0.003 Tc
+-0.001 Tw
+[( LX)10(IV)10(, Octobe)19(r, pp: )20( 416)19(-24)]TJ
+-10.26 -2.3 TD
+0.004 Tc
+0.238 Tw
+[(Tul)6(l)6(o)0(ck, G. )20(\(1980)20(\) \223)17(F)-5(ede)20(ral)6(i)6(s)4(m: P)11(r)-3(o)20(b)0(l)6(e)0(ms o)20(f)2( S)11(c)4(al)6(e\224 )-20( )-20(i)6(n)0( Grew)6(al)6(, )-20(B)11(haj)6(a)20(n)0( )-20(S)11(.)]TJ
+3 -1.16 TD
+0.003 Tc
+0.379 Tw
+[(Geoffrey B)10(r)16(ennan)19( and R)5(u)-1(ss)23(el)5( L. M)16(a)-1(thew)5(s eds.)21( )]TJ
+12 0 2.551 12 419.52 177.2 Tm
+0.004 Tc
+[(Th)20(e E)11(c)4(onomi)6(cs o)20(f)]TJ
+-23.4334 -1.16 TD
+0.005 Tc
+[(Feder)18(al)7(i)7(s)5(m)]TJ
+12 0 0 12 194.88 163.28 Tm
+0.003 Tc
+-0.001 Tw
+[( \(A)10(ust)21(r)-4(al)5(i)5(an N)5(a)-1(ti)5(o)19(nal)5( U)5(n)-1(i)5(v)3(ersi)5(ty)23(: C)5(anbe)19(rra,)21( A)10(u)-1(stral)5(i)5(a)-1(\))]TJ
+ET
+endstream endobj 302 0 obj << /ProcSet [ /PDF /Text ] /Font << /F5 121 0 R >> /ExtGState << /GS1 122 0 R >> >> endobj 303 0 obj << /Type /Halftone /HalftoneType 1 /HalftoneName (Default) /Frequency 60 /Angle 45 /SpotFunction /Round >> endobj 304 0 obj << /Type /Encoding /Differences [ 0 /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /ring /cedilla /hungarumlaut /ogonek /caron /dotlessi /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet /bullet 39 /quotesingle 96 /grave 127 /bullet /bullet /bullet /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE /bullet /bullet /bullet /bullet /quoteleft /quoteright /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe /bullet /bullet /Ydieresis /space 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine 188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] >> endobj 305 0 obj << /Count 16 /First 3 0 R /Last 117 0 R >> endobj 306 0 obj << /Type /Catalog /Pages 151 0 R /Outlines 305 0 R /OpenAction [ 1 0 R /Fit ] /PageMode /UseOutlines >> endobj 307 0 obj << /CreationDate (D:19981120125044) /Producer (\376\377\000A\000c\000r\000o\000b\000a\000t\000 \000D\000i\000s\000t\000\ i\000l\000l\000e\000r\000 \0003\000.\0000\0001\000 \000f\000o\000r\000 \000\ W\000i\000n\000d\000o\000w\000s) /Creator (PSCRIPT.DRV Version 4.0) /Title (Microsoft Word - Tsy WP 98-7.doc) /ModDate (D:19981120133920) >> endobj xref 0 308 0000000030 65535 f
+0000000016 00000 n
+0000000000 00001 f
+0000000108 00000 n
+0000000206 00000 n
+0000000298 00000 n
+0000000011 00001 f
+0000000429 00000 n
+0000000002 00001 f
+0000000008 00001 f
+0000000009 00001 f
+0000000010 00001 f
+0000000006 00001 f
+0000000521 00000 n
+0000000012 00001 f
+0000000014 00001 f
+0000000015 00001 f
+0000000016 00001 f
+0000000614 00000 n
+0000000707 00000 n
+0000000017 00001 f
+0000000838 00001 n
+0000000897 00000 n
+0000000990 00001 n
+0000001049 00000 n
+0000001142 00001 n
+0000001201 00000 n
+0000001294 00000 n
+0000000056 00001 f
+0000001446 00000 n
+0000000028 00001 f
+0000001539 00000 n
+0000001632 00000 n
+0000000077 00001 f
+0000001801 00000 n
+0000000033 00001 f
+0000001894 00000 n
+0000000035 00001 f
+0000000020 00001 f
+0000001987 00000 n
+0000000044 00001 f
+0000002080 00000 n
+0000000038 00001 f
+0000000042 00001 f
+0000000045 00001 f
+0000000049 00001 f
+0000000043 00001 f
+0000002173 00000 n
+0000000046 00001 f
+0000000048 00001 f
+0000002266 00000 n
+0000000040 00001 f
+0000002359 00000 n
+0000000037 00001 f
+0000002452 00000 n
+0000000053 00001 f
+0000000060 00001 f
+0000002545 00000 n
+0000000055 00001 f
+0000002638 00000 n
+0000000058 00001 f
+0000002731 00000 n
+0000002824 00000 n
+0000002958 00000 n
+0000000075 00001 f
+0000000066 00001 f
+0000000067 00001 f
+0000000068 00001 f
+0000000069 00001 f
+0000000051 00001 f
+0000000065 00001 f
+0000003051 00000 n
+0000000070 00001 f
+0000003144 00000 n
+0000000072 00001 f
+0000000074 00001 f
+0000003237 00000 n
+0000000088 00001 f
+0000003330 00000 n
+0000003423 00000 n
+0000000086 00001 f
+0000000064 00001 f
+0000003595 00000 n
+0000000085 00001 f
+0000003688 00000 n
+0000000081 00001 f
+0000000083 00001 f
+0000003781 00000 n
+0000000104 00001 f
+0000003874 00000 n
+0000003967 00000 n
+0000004116 00000 n
+0000000093 00001 f
+0000000094 00001 f
+0000000095 00001 f
+0000000080 00001 f
+0000004209 00000 n
+0000004302 00000 n
+0000004461 00000 n
+0000000092 00001 f
+0000004600 00000 n
+0000000099 00001 f
+0000000101 00001 f
+0000004694 00000 n
+0000000102 00001 f
+0000004788 00000 n
+0000004882 00000 n
+0000005037 00000 n
+0000005131 00000 n
+0000005312 00000 n
+0000005406 00001 n
+0000005540 00001 n
+0000005574 00000 n
+0000005668 00000 n
+0000005812 00000 n
+0000005906 00000 n
+0000006056 00000 n
+0000006150 00000 n
+0000006255 00000 n
+0000012198 00000 n
+0000012316 00000 n
+0000012428 00000 n
+0000012535 00000 n
+0000012614 00000 n
+0000012763 00000 n
+0000012857 00000 n
+0000028372 00000 n
+0000028515 00000 n
+0000028623 00000 n
+0000028733 00000 n
+0000028843 00000 n
+0000028937 00000 n
+0000037541 00000 n
+0000037696 00000 n
+0000044165 00000 n
+0000044283 00000 n
+0000051045 00000 n
+0000051163 00000 n
+0000057802 00000 n
+0000057920 00000 n
+0000058014 00000 n
+0000066563 00000 n
+0000066681 00000 n
+0000074216 00000 n
+0000074334 00000 n
+0000083030 00000 n
+0000083148 00000 n
+0000090527 00000 n
+0000090645 00000 n
+0000090739 00000 n
+0000095638 00000 n
+0000095744 00000 n
+0000095888 00000 n
+0000096039 00000 n
+0000103621 00000 n
+0000103739 00000 n
+0000111638 00000 n
+0000111756 00000 n
+0000119864 00000 n
+0000119982 00000 n
+0000128148 00000 n
+0000128266 00000 n
+0000128360 00000 n
+0000155481 00000 n
+0000155599 00000 n
+0000162305 00000 n
+0000162423 00000 n
+0000170079 00000 n
+0000170210 00000 n
+0000170296 00000 n
+0000178638 00000 n
+0000178744 00000 n
+0000186735 00000 n
+0000186841 00000 n
+0000186935 00000 n
+0000198539 00000 n
+0000198670 00000 n
+0000198823 00000 n
+0000198917 00000 n
+0000206502 00000 n
+0000206621 00000 n
+0000210734 00000 n
+0000210865 00000 n
+0000225767 00000 n
+0000225885 00000 n
+0000237838 00000 n
+0000237981 00000 n
+0000245049 00000 n
+0000245167 00000 n
+0000245261 00000 n
+0000254582 00000 n
+0000254688 00000 n
+0000262602 00000 n
+0000262720 00000 n
+0000262814 00000 n
+0000264188 00000 n
+0000264294 00000 n
+0000271854 00000 n
+0000271972 00000 n
+0000279022 00000 n
+0000279140 00000 n
+0000279291 00000 n
+0000287760 00000 n
+0000287878 00000 n
+0000295535 00000 n
+0000295653 00000 n
+0000295747 00000 n
+0000304159 00000 n
+0000304265 00000 n
+0000315597 00000 n
+0000315715 00000 n
+0000315809 00000 n
+0000319315 00000 n
+0000319421 00000 n
+0000327411 00000 n
+0000327542 00000 n
+0000336211 00000 n
+0000336329 00000 n
+0000344508 00000 n
+0000344626 00000 n
+0000355796 00000 n
+0000355914 00000 n
+0000356008 00000 n
+0000362463 00000 n
+0000362581 00000 n
+0000362737 00000 n
+0000370212 00000 n
+0000370330 00000 n
+0000370424 00000 n
+0000379030 00000 n
+0000379136 00000 n
+0000386068 00000 n
+0000386186 00000 n
+0000386280 00000 n
+0000393734 00000 n
+0000393840 00000 n
+0000393934 00000 n
+0000401156 00000 n
+0000401262 00000 n
+0000401356 00000 n
+0000407495 00000 n
+0000407601 00000 n
+0000413880 00000 n
+0000414011 00000 n
+0000421223 00000 n
+0000421354 00000 n
+0000428764 00000 n
+0000428882 00000 n
+0000428976 00000 n
+0000429483 00000 n
+0000429589 00000 n
+0000429748 00000 n
+0000435472 00000 n
+0000435590 00000 n
+0000435684 00000 n
+0000444663 00000 n
+0000444781 00000 n
+0000444875 00000 n
+0000454225 00000 n
+0000454343 00000 n
+0000454437 00000 n
+0000463241 00000 n
+0000463347 00000 n
+0000463441 00000 n
+0000472115 00000 n
+0000472221 00000 n
+0000472315 00000 n
+0000480096 00000 n
+0000480214 00000 n
+0000480308 00000 n
+0000487448 00000 n
+0000487566 00000 n
+0000495365 00000 n
+0000495483 00000 n
+0000495577 00000 n
+0000502766 00000 n
+0000502884 00000 n
+0000511436 00000 n
+0000511554 00000 n
+0000511713 00000 n
+0000511807 00000 n
+0000521078 00000 n
+0000521184 00000 n
+0000530540 00000 n
+0000530658 00000 n
+0000530752 00000 n
+0000537957 00000 n
+0000538075 00000 n
+0000538169 00000 n
+0000542042 00000 n
+0000542160 00000 n
+0000550234 00000 n
+0000550352 00000 n
+0000550446 00000 n
+0000554592 00000 n
+0000554698 00000 n
+0000561501 00000 n
+0000561619 00000 n
+0000561713 00000 n
+0000568589 00000 n
+0000568695 00000 n
+0000568789 00000 n
+0000575803 00000 n
+0000575909 00000 n
+0000576040 00000 n
+0000577607 00000 n
+0000577672 00000 n
+0000577800 00000 n
+trailer << /Size 308 /Info 307 0 R /Root 306 0 R /ID[<7ddd760ba1955f40826faf1aa6a273d8><5a006ce8bb876b5a1a031c0ea3105aa7>] >> startxref 578158 %%EOF 2 1 obj << /Title () /Dest [ null /FitH 261 ] /Parent 8 1 R /First 310 0 R /Last 308 0 R /Count 3 >> endobj 3 0 obj << /Title (ABSTRACT) /Dest [ 1 0 R /FitH 468 ] /Parent 305 0 R /Next 28 1 R >> endobj 5 0 obj << /Title (EXECUTIVE SUMMARY) /Dest [ 4 0 R /FitH 757 ] /Parent 305 0 R /Prev 28 1 R /Next 19 0 R /Count 0 >> endobj 6 1 obj << /Title (3\tPOLITICAL/SOCIAL DECISION MAKING AND COST BEARING) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 316 0 R /Next 12 1 R /First 315 0 R /Last 11 1 R /Count 13 >> endobj 8 1 obj << /Title (Sources of Interjurisdictional Externalities) /Dest [ null /FitH 287 ] /Parent 9 1 R /Prev 311 0 R /First 2 1 R /Last 2 1 R /Count 4 >> endobj 9 1 obj << /Title (Balanced decision making) /Dest [ null /FitH 158 ] /Parent 11 1 R /Prev 313 0 R /Next 10 1 R /First 312 0 R /Last 8 1 R /Count 7 >> endobj 10 1 obj << /Title (Cost effective decision making) /Dest [ null /FitH 757 ] /Parent 11 1 R /Prev 9 1 R >> endobj 11 1 obj << /Title (When does Devolution Improve Social Choice?) /Dest [ null /FitH 699 ] /Parent 6 1 R /Prev 314 0 R /First 313 0 R /Last 10 1 R /Count 10 >> endobj 12 1 obj << /Title (EXAMPLE: THE PLACEMENT OF CELL PHONE TOWERS) /Dest [ null /FitH 726 ] /Parent 88 1 R /Prev 6 1 R /Next 14 1 R >> endobj 13 0 obj << /Type /Page /Parent 37 1 R /Resources 138 0 R /Contents 137 0 R >> endobj 14 1 obj << /Title (EXAMPLE: THE PLACEMENT OF CELL PHONE TOWERS CONTINUED) /Dest [ null /FitH 250 ] /Parent 88 1 R /Prev 12 1 R /Next 17 1 R >> endobj 15 1 obj << /Title (The Framework: Political Decision Making and Cost Bearing) /Dest [ null /FitH 740 ] /Parent 17 1 R /Next 16 1 R >> endobj 16 1 obj << /Title (Mobility and Devolution) /Dest [ null /FitH 684 ] /Parent 17 1 R /Prev 15 1 R >> endobj 17 1 obj << /Title (Figure xxx) /Dest [ null /FitH 220 ] /Parent 88 1 R /Prev 14 1 R /Next 69 1 R /First 15 1 R /Last 16 1 R /Count 2 >> endobj 18 0 obj << /Type /Page /Parent 37 1 R /Resources 143 0 R /Contents 142 0 R >> endobj 20 1 obj << /Title (Innovation) /Dest [ null /FitH 424 ] /Parent 38 1 R >> endobj 22 0 obj << /Type /Page /Parent 37 1 R /Resources 145 0 R /Contents 144 0 R >> endobj 24 0 obj << /Type /Page /Parent 37 1 R /Resources 147 0 R /Contents 146 0 R >> endobj 28 1 obj << /Title (CONTENTS) /A 130 1 R /Next 5 0 R /Prev 3 0 R /Parent 305 0 R >> endobj 30 1 obj << /S /GoTo /D [ 1 0 R /FitH 468 ] >> endobj 33 1 obj << /Length 15743 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F3 1 Tf
+13.92 0 0 13.92 281.76 726.793 Tm
+0 0 0 rg
+0.002 Tc
+[(Co)10(n)-8(t)7(e)-11(n)10(t)-10(s)]TJ
+/F7 1 Tf
+10.08 0 0 10.08 99.36 708.556 Tm
+0.012 Tc
+0 Tw
+[(E)12(X)20(E)12(C)20(U)20(T)12(I)20(V)20(E)12( S)20(U)20(M)27(MA)20(R)43(Y)-169(..............................................................................................................)]TJ
+40.4292 0 TD
+[(....)-213(3)]TJ
+-40.4292 -2.3333 TD
+-0.008 Tc
+[(1)-1889(INT)-8(RO)-16(DUCT)-8(IO)-16(N)]TJ
+10.5714 0 TD
+0.012 Tc
+[(......................................................................................................................)-213(7)]TJ
+/F9 1 Tf
+-8.1905 -1.7141 TD
+-0.024 Tw
+[(D)20(evo)36(lu)12(t)28(i)4(o)12(n)12( a)12(n)12(d)36( )-24(d)12(e)27(cen)36(tr)20(a)12(l)28(is)20(a)12(t)4(i)28(o)12(n)-33(................................................................................................)]TJ
+38.0476 0 TD
+[(....)-214(7)]TJ
+-38.0476 -1.1429 TD
+0 Tc
+0.012 Tw
+[(T)8(h)0(e)-8( )24(R)-8(e)-8(s)8(our)32(c)-8(e)15( Mana)24(ge)-8(m)31(e)-8(nt)16( A)16(c)-8(t)]TJ
+12.6429 0 TD
+0.012 Tc
+[(.....................................................................................................)-214(8)]TJ
+-12.6429 -1.1429 TD
+0 Tw
+[(Aim)20(s)20( a)36(n)12(d)12( s)44(t)4(r)20(u)12(ct)28(u)12(r)20(e)27( o)12(f)28( th)36(is)20( p)12(a)36(p)12(e)4(r)-49(...............................................................................................)]TJ
+37.7871 0 TD
+[(.....)-214(9)]TJ
+/F7 1 Tf
+-40.168 -1.7621 TD
+[(2)-1869(W)12(H)28(Y)-4( A)20(N)20(D)43( W)36(H)4(A)20(T)12( S)44(HOU)43(L)14(D)20( W)36(E)12( R)20(E)36(GU)20(L)12(A)20(T)12(E)36(?)-82(...................................................................)-238(1)12(1)]TJ
+/F11 1 Tf
+1.1905 -2.3093 TD
+0 Tc
+(E)Tj
+7.92 0 0 7.92 117.6 603.472 Tm
+-0.003 Tc
+0.026 Tw
+[(X)22(T)-28(ERN)-39(A)22(LIT)-28(I)-3(ES)-23( A)22(N)-8(D)-8( )]TJ
+10.08 0 0 10.08 195.36 603.678 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 201.12 603.472 Tm
+0.003 Tc
+[(UBL)8(I)3(C)-27( )]TJ
+10.08 0 0 10.08 227.04 603.678 Tm
+0 Tc
+(G)Tj
+7.92 0 0 7.92 234.24 603.472 Tm
+0.005 Tc
+[(OOD)-31(S)]TJ
+10.08 0 0 10.08 256.08 603.678 Tm
+0.012 Tc
+[(.................................................................................................)-238(1)12(1)]TJ
+-14.3571 -1.7381 TD
+0 Tc
+(I)Tj
+7.92 0 0 7.92 114.72 585.952 Tm
+0.003 Tc
+0.02 Tw
+[(NF)13(ORM)-17(A)28(T)-22(I)3(ON F)-17(A)28(IL)-22(URE)-22(S)]TJ
+10.08 0 0 10.08 208.56 586.158 Tm
+0.012 Tc
+[(...................................................................................................................)-237(1)12(2)]TJ
+/F7 1 Tf
+-10.8333 -1.7383 TD
+-0.008 Tc
+[(3)-1889(P)8(O)-16(L)-8(IT)-8(ICAL)-8(/)-16(S)0(O)-16(CIAL)-8( D)25(E)-8(CISIO)-16(N )24(M)-17(A)0(K)-16(ING)8( AND C)23(O)-16(ST)16( )24(B)-32(E)-8(ARING)]TJ
+32.0476 0 TD
+0.012 Tc
+[(..................................)-238(1)12(3)]TJ
+/F11 1 Tf
+-30.8571 -2.3093 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 545.152 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 545.358 Tm
+0 Tc
+(P)Tj
+7.92 0 0 7.92 135.6 545.152 Tm
+-0.001 Tc
+-0.007 Tw
+[(ROBL)-26(EM)-21( WIT)-26(H)-6( )]TJ
+10.08 0 0 10.08 193.68 545.358 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 199.44 545.152 Tm
+-0.001 Tc
+[(U)24(B)-31(LIC )]TJ
+10.08 0 0 10.08 225.12 545.358 Tm
+0 Tc
+(G)Tj
+7.92 0 0 7.92 232.56 545.152 Tm
+0.005 Tc
+(OODS)Tj
+10.08 0 0 10.08 254.16 545.358 Tm
+0.008 Tc
+0.004 Tw
+(: P)Tj
+7.92 0 0 7.92 265.2 545.152 Tm
+-0.001 Tc
+[(REF)-21(E)4(RE)-26(NCE )]TJ
+10.08 0 0 10.08 312.96 545.358 Tm
+0 Tc
+0 Tw
+(R)Tj
+7.92 0 0 7.92 319.68 545.152 Tm
+-0.001 Tc
+[(E)-26(V)24(EL)-26(A)24(T)-26(ION)]TJ
+10.08 0 0 10.08 366.96 545.358 Tm
+0.012 Tc
+[(.......................................................)-237(1)12(3)]TJ
+-25.3571 -1.7381 TD
+0 Tc
+(S)Tj
+7.92 0 0 7.92 116.88 527.632 Tm
+0.003 Tc
+[(OCI)-28(A)28(L)8( )]TJ
+10.08 0 0 10.08 143.04 527.838 Tm
+0 Tc
+(C)Tj
+7.92 0 0 7.92 149.76 527.632 Tm
+0.003 Tc
+[(HOI)-28(CE)8( )]TJ
+10.08 0 0 10.08 176.16 527.838 Tm
+0 Tc
+(M)Tj
+7.92 0 0 7.92 185.28 527.632 Tm
+-0.006 Tc
+[(ECH)-42(A)19(N)-11(I)-37(SM)-26(S)]TJ
+10.08 0 0 10.08 232.32 527.838 Tm
+0.012 Tc
+[(..........................................................................................................)-238(1)12(4)]TJ
+-12 -1.7381 TD
+0 Tc
+(W)Tj
+7.92 0 0 7.92 120.72 510.112 Tm
+0.005 Tc
+-0.013 Tw
+[(HE)10(N DO)-31(E)10(S)-15( )]TJ
+10.08 0 0 10.08 162 510.318 Tm
+0 Tc
+0 Tw
+(D)Tj
+7.92 0 0 7.92 169.2 510.112 Tm
+0.004 Tc
+[(E)-21(V)29(OL)-21(U)29(T)-21(ION )]TJ
+10.08 0 0 10.08 217.2 510.318 Tm
+0 Tc
+(I)Tj
+7.92 0 0 7.92 220.8 510.112 Tm
+[(M)10(P)-20(RO)-36(V)25(E)-25( )]TJ
+10.08 0 0 10.08 256.08 510.318 Tm
+(S)Tj
+7.92 0 0 7.92 261.6 510.112 Tm
+0.003 Tc
+[(OCI)-28(A)-2(L)8( )]TJ
+10.08 0 0 10.08 288 510.318 Tm
+0 Tc
+(C)Tj
+7.92 0 0 7.92 294.72 510.112 Tm
+0.002 Tc
+(HOICE)Tj
+10.08 0 0 10.08 319.2 510.318 Tm
+0.012 Tc
+[(?)-92(.......................................................................)-238(1)12(6)]TJ
+/F9 1 Tf
+-19.4286 -1.1429 TD
+[(I)12(n)12(f)4(o)12(r)20(m)20(e)4(d)36( d)36(ecis)44(io)12(n)36( m)20(a)12(k)27(i)4(n)12(g)-153(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(1)12(6)]TJ
+-37.5241 -1.1429 TD
+[(Ba)12(la)12(n)36(c)27(ed)12( d)36(e)4(c)27(i)4(s)20(i)4(o)12(n)36( m)20(a)36(kin)12(g)-34(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(1)12(7)]TJ
+-37.5241 -1.1429 TD
+[(C)12(o)12(s)20(t )24(ef)28(fe)27(cti)28(ve)27( d)36(e)4(c)27(i)4(s)20(i)4(o)12(n)36( m)20(a)12(k)27(i)4(n)12(g)14(.................................................................................................)]TJ
+37.5238 0 TD
+[(....)-238(2)12(2)]TJ
+/F11 1 Tf
+-38.7143 -1.7381 TD
+0 Tc
+(T)Tj
+7.92 0 0 7.92 117.6 458.032 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 458.238 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 458.032 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 458.238 Tm
+0.008 Tc
+0.004 Tw
+(: P)Tj
+7.92 0 0 7.92 193.92 458.032 Tm
+0 Tc
+[(OLIT)-25(IC)-30(A)25(L)-25( )]TJ
+10.08 0 0 10.08 232.8 458.238 Tm
+0 Tw
+(D)Tj
+7.92 0 0 7.92 240 458.032 Tm
+0.004 Tc
+[(E)9(C)4(I)-27(S)14(ION )]TJ
+10.08 0 0 10.08 273.6 458.238 Tm
+0 Tc
+(M)Tj
+7.92 0 0 7.92 282.72 458.032 Tm
+0.004 Tc
+0.019 Tw
+[(AK)29(ING A)29(N)-1(D)-32( )]TJ
+10.08 0 0 10.08 329.52 458.238 Tm
+0 Tc
+0 Tw
+(C)Tj
+7.92 0 0 7.92 336.24 458.032 Tm
+0.005 Tc
+[(OS)15(T)-20( )]TJ
+10.08 0 0 10.08 353.28 458.238 Tm
+0 Tc
+(B)Tj
+7.92 0 0 7.92 359.76 458.032 Tm
+[(E)-25(A)-5(RIN)-36(G)]TJ
+10.08 0 0 10.08 390.72 458.238 Tm
+0.012 Tc
+[(..............................................)-237(2)12(5)]TJ
+-27.7143 -1.7381 TD
+0 Tc
+(M)Tj
+7.92 0 0 7.92 120.24 440.512 Tm
+0.003 Tc
+0.02 Tw
+[(OBIL)8(IT)-22(Y A)28(ND )]TJ
+10.08 0 0 10.08 173.28 440.718 Tm
+0 Tc
+0 Tw
+(D)Tj
+7.92 0 0 7.92 180.72 440.512 Tm
+0.004 Tc
+[(E)-21(V)29(OL)-21(U)29(T)-21(ION)]TJ
+10.08 0 0 10.08 227.04 440.718 Tm
+0.012 Tc
+[(............................................................................................................)-238(2)12(7)]TJ
+/F7 1 Tf
+-12.6667 -1.7621 TD
+[(4)-1869(I)20(MP)28(L)12(E)12(M)3(E)12(N)20(T)12(A)43(T)12(I)20(ON)21(...............................................................................................................)-237(2)]TJ
+41.6906 0 TD
+0 Tc
+(9)Tj
+/F9 1 Tf
+-39.3096 -1.7141 TD
+0.012 Tc
+[(D)20(i)4(s)20(eco)12(n)36(o)12(m)20(i)28(es)20( o)12(f)28( s)20(c)27(a)12(l)4(e)27(:)12( )24(fl)28(exi)28(b)12(i)4(l)28(i)4(t)28(y)-208(.............................................................................................)]TJ
+37.787 0 TD
+[(...)-237(3)12(0)]TJ
+-37.787 -1.1191 TD
+0.001 Tw
+[(Eco)11(n)35(o)11(m)19(ies)43( o)11(f)27( s)19(c)3(a)35(l)3(e)26(:)11( )24(eff)27(ic)26(ien)35(c)26(y)-67(.................................................................................................)]TJ
+37.5238 0 TD
+[(....)-238(3)12(1)]TJ
+-37.5238 -1.1429 TD
+[(I)12(n)12(f)4(o)12(r)20(m)20(a)12(t)28(i)4(o)12(n)-11(....................................................................................................................)]TJ
+35.1676 0 TD
+[(.............)-238(3)12(2)]TJ
+-35.1676 -1.1429 TD
+0 Tc
+[(Innov)-8(a)24(t)-8(i)-8(o)24(n)]TJ
+4.5238 0 TD
+0.012 Tc
+(...............................................................................................................................)Tj
+33.2633 0 TD
+[(...)-238(3)12(2)]TJ
+/F11 1 Tf
+-38.9776 -1.7381 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 353.632 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 353.838 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 353.632 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 353.838 Tm
+0.008 Tc
+0.004 Tw
+(: E)Tj
+7.92 0 0 7.92 194.64 353.632 Tm
+0 Tc
+[(F)10(F)10(ICI)-31(ENT)-25( )]TJ
+10.08 0 0 10.08 231.6 353.838 Tm
+0 Tw
+(I)Tj
+7.92 0 0 7.92 234.96 353.632 Tm
+0.001 Tc
+[(M)-19(P)11(LE)-24(M)11(E)6(NT)-55(A)26(T)-24(ION)]TJ
+10.08 0 0 10.08 306.24 353.838 Tm
+0.012 Tc
+[(..............................................................................)-237(3)12(4)]TJ
+/F7 1 Tf
+-20.5238 -1.7621 TD
+-0.008 Tc
+0.02 Tw
+[(5)-1889(CAN W)-8(E)-8( S)24(E)-8(P)8(ARAT)-8(E)-8( DE)-6(CISIO)-16(N )24(M)-17(A)23(K)-16(ING)-16( F)8(R)0(O)8(M)7( IM)-17(P)8(L)-8(E)16(M)-17(E)-8(N)0(T)-8(A)0(T)-8(I)24(O)-16(N)0(?)]TJ
+35.1905 0 TD
+0.012 Tc
+[(......................)-237(3)12(6)]TJ
+/F9 1 Tf
+-32.8095 -1.7141 TD
+0 Tc
+0.012 Tw
+[(Cont)-8(r)8(a)0(c)15(t)-8(i)-8(n)24(g pr)8(o)24(b)0(l)-8(e)-8(m)8(s)]TJ
+8.9762 0 TD
+0.012 Tc
+[(.................................................................................................................)-237(3)12(6)]TJ
+-8.9762 -1.1429 TD
+0 Tw
+[(S)12(o)12(l)4(u)12(t)28(io)12(n)12(s)20( )24(to)36( co)36(n)12(t)4(r)20(a)12(c)27(tin)36(g)12( p)12(r)20(o)12(b)36(lem)20(s)-168(..............................................................................................)]TJ
+38.3109 0 TD
+0.249 Tc
+[(.3)249(7)]TJ
+-38.3109 -1.1429 TD
+0.009 Tc
+0.003 Tw
+[(Ad)9(va)33(n)9(t)1(a)9(g)33(es)17( o)33(f)1( s)41(e)1(p)9(a)9(r)17(a)9(t)25(in)9(g)33( p)9(o)33(lit)25(ica)33(l )24(a)9(n)9(d)33( im)17(p)33(lem)17(e)24(n)9(ta)33(tio)9(n)33( r)17(o)9(l)25(e)1(s)17(:)9( )24(th)9(e)24( r)17(e)24(g)9(u)9(l)1(a)33(t)1(o)9(r)17( )24(/ p)9(r)17(o)33(v)1(i)25(d)9(er)17( s)17(p)33(li)25(t)-183(.........)-241(3)9(8)]TJ
+/F11 1 Tf
+-1.1905 -1.7381 TD
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 117.6 278.032 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 130.08 278.238 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 135.6 278.032 Tm
+0.03 Tc
+[(RA)55(M)10(E)35(W)34(O)25(RK)]TJ
+10.08 0 0 10.08 182.88 278.238 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 194.64 278.032 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 207.12 278.238 Tm
+0 Tc
+0 Tw
+(W)Tj
+7.92 0 0 7.92 216.48 278.032 Tm
+-0.005 Tc
+[(H)-10(O)-41(LE )]TJ
+10.08 0 0 10.08 239.76 278.238 Tm
+0 Tc
+(P)Tj
+7.92 0 0 7.92 245.28 278.032 Tm
+0.031 Tc
+[(IC)31(T)6(U)56(RE)]TJ
+10.08 0 0 10.08 274.56 278.238 Tm
+0.012 Tc
+[(..........................................................................................)-237(3)12(9)]TJ
+/F7 1 Tf
+-17.3809 -1.7621 TD
+-0.008 Tc
+-0.004 Tw
+[(6)-1889(ACCO)-16(UNT)-8(A)23(B)-32(IL)-8(IT)-8(Y O)-16(F)8( )-22(G)8(O)-16(VE)-8(RN)23(M)-17(E)-8(NT)]TJ
+21.0476 0 TD
+0.012 Tc
+[(............................................................................)-238(4)12(1)]TJ
+/F9 1 Tf
+-18.6667 -1.7141 TD
+0 Tw
+[(S)12(o)12(ver)44(eig)12(n)36(t)4(y)27( is)20(s)20(u)36(es)-74(.............................................................................................................)]TJ
+35.953 0 TD
+[(..........)-237(4)12(3)]TJ
+/F7 1 Tf
+-38.3339 -1.7383 TD
+-0.008 Tc
+[(AP)8(P)8(E)-8(NDICE)-8(S)]TJ
+6.3809 0 TD
+0.012 Tc
+(...............................................................................................................................)Tj
+33.2633 0 TD
+[(.....)-238(4)12(7)]TJ
+/F11 1 Tf
+-38.4538 -2.3093 TD
+0 Tc
+(A)Tj
+7.92 0 0 7.92 118.56 202.192 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 202.398 Tm
+0 Tc
+(O)Tj
+7.92 0 0 7.92 161.28 202.192 Tm
+0.036 Tc
+(NE)Tj
+10.08 0 0 10.08 172.08 202.398 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 183.84 202.192 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 196.32 202.398 Tm
+0 Tc
+0 Tw
+(R)Tj
+7.92 0 0 7.92 202.8 202.192 Tm
+[(E)-25(S)10(O)-36(U)25(RCE)-25( )]TJ
+10.08 0 0 10.08 241.2 202.398 Tm
+(M)Tj
+7.92 0 0 7.92 250.32 202.192 Tm
+-0.025 Tc
+[(AN)-61(AG)-61(E)-20(M)-15(E)-50(N)-30(T)-50( )]TJ
+10.08 0 0 10.08 302.88 202.398 Tm
+0 Tc
+(A)Tj
+7.92 0 0 7.92 310.08 202.192 Tm
+[(CT)-25( )]TJ
+10.08 0 0 10.08 322.32 202.398 Tm
+(1991)Tj
+2.0714 0 TD
+0.012 Tc
+[(................................................................)-237(4)12(7)]TJ
+/F9 1 Tf
+-21.8095 -1.1429 TD
+[(M)12(a)12(j)4(o)12(r)20( )24(As)20(p)12(e)27(cts)44( o)12(f)28( t)28(h)12(e)27( RM)35(A)6(.......................................................................................................)]TJ
+37.5241 0 TD
+[(....)-238(4)12(7)]TJ
+-37.5241 -1.1429 TD
+[(Ro)12(l)28(e)4( o)36(f)4( )24(C)12(e)4(n)36(t)4(r)20(a)12(l)28( G)20(o)12(v)27(e)4(r)20(n)12(m)20(e)4(n)36(t)-41(.....................................................................................................)]TJ
+37.7859 0 TD
+[(...)-238(4)12(8)]TJ
+-37.7859 -1.1429 TD
+[(Ro)12(l)28(e)4(s)20( o)36(f)4( L)20(o)36(ca)12(l)28( A)28(u)12(th)12(o)12(r)44(iti)28(es)-121(.....................................................................................................)]TJ
+37.0002 0 TD
+[(......)-238(4)12(8)]TJ
+-37.0002 -1.1429 TD
+[(P)28(u)12(b)12(lic)27( P)28(a)12(r)20(t)4(i)28(cip)12(a)36(tio)36(n)-34(...........................................................................................................)]TJ
+36.2148 0 TD
+[(.........)-237(4)12(9)]TJ
+-36.2148 -1.1429 TD
+[(L)20(o)12(ca)12(l)28( G)20(o)12(v)27(e)4(r)20(n)12(m)20(e)4(n)36(t)4( )24(Re)27(fo)12(r)20(m)-193(........................................................................................................)]TJ
+38.048 0 TD
+[(..)-238(4)12(9)]TJ
+/F11 1 Tf
+-39.2384 -1.7381 TD
+0 Tc
+(A)Tj
+7.92 0 0 7.92 118.56 127.072 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 127.278 Tm
+0 Tc
+(T)Tj
+7.92 0 0 7.92 160.32 127.072 Tm
+-0.004 Tc
+(WO)Tj
+10.08 0 0 10.08 173.52 127.278 Tm
+0.008 Tc
+0.004 Tw
+(: W)Tj
+7.92 0 0 7.92 188.4 127.072 Tm
+0.004 Tc
+0.019 Tw
+[(HY A)29(ND W)8(H)-32(A)29(T)-21( )31(S)14(H)-1(O)-32(U)-1(L)9(D)-1( W)8(E)9( RE)9(G)-32(U)29(L)-21(A)29(T)-21(E)]TJ
+10.08 0 0 10.08 338.4 127.278 Tm
+0.012 Tc
+[(?)-20(................................................................)-237(5)12(1)]TJ
+/F9 1 Tf
+-21.3333 -1.1429 TD
+0.001 Tw
+[(Ext)27(er)19(n)11(a)35(lit)27(ies)43( /)27( I)11(n)35(co)11(m)19(p)11(l)27(e)3(t)27(e)3( )24(Al)27(lo)11(ca)35(ti)27(o)11(n)11( o)35(f)3( P)27(r)19(o)11(p)35(er)19(ty)26( R)27(i)3(g)11(h)35(ts)-96(..............................................................)-238(5)11(1)]TJ
+T*
+0 Tw
+[(I)12(n)12(f)4(o)12(r)20(m)20(a)12(t)28(i)4(o)12(n)36( F)28(a)12(ilu)12(r)44(e)4(s)-74(...........................................................................................................)]TJ
+36.4767 0 TD
+[(........)-237(5)12(6)]TJ
+-36.4767 -1.1429 TD
+0.001 Tw
+[(W)34(h)11(a)11(t)3( is)19( )24(th)35(e r)19(o)35(le)26( o)11(f)27( th)35(e )24(RM)34(A?)13(...................................................................................................)]TJ
+37.5239 0 TD
+[(....)-238(5)12(7)]TJ
+ET
+endstream endobj 35 1 obj << /Type /Page /Parent 123 0 R /Resources 77 1 R /Contents 33 1 R >> endobj 37 1 obj << /Type /Pages /Kids [ 13 0 R 139 0 R 18 0 R 22 0 R 24 0 R ] /Count 5 /Parent 151 0 R >> endobj 38 1 obj << /Title () /Dest [ null /FitH 424 ] /Parent 42 1 R /First 20 1 R /Last 20 1 R /Count 1 >> endobj 40 1 obj << /Title (Innovation) /Dest [ null /FitH 280 ] /Parent 69 1 R /Prev 44 1 R /Next 51 1 R >> endobj 42 1 obj << /Title () /Dest [ null /FitH 424 ] /Parent 43 1 R /First 38 1 R /Last 38 1 R /Count 2 >> endobj 43 1 obj << /Title () /Dest [ null /FitH 424 ] /Parent 46 1 R /First 42 1 R /Last 42 1 R /Count 3 >> endobj 44 1 obj << /Title (Information) /Dest [ null /FitH 587 ] /Parent 69 1 R /Prev 45 1 R /Next 40 1 R >> endobj 45 1 obj << /Title (Economies of scale: efficiency) /Dest [ null /FitH 530 ] /Parent 69 1 R /Prev 49 1 R /Next 44 1 R >> endobj 46 1 obj << /Title () /Dest [ null /FitH 424 ] /Parent 48 1 R /First 43 1 R /Last 43 1 R /Count 4 >> endobj 48 1 obj << /Title () /Dest [ null /FitH 424 ] /Parent 69 1 R /Next 49 1 R /First 46 1 R /Last 46 1 R /Count 5 >> endobj 49 1 obj << /Title (Diseconomies of scale: flexibility) /Dest [ null /FitH 240 ] /Parent 69 1 R /Prev 48 1 R /Next 45 1 R >> endobj 51 1 obj << /Title (The Framework: Efficient Implementation) /Dest [ null /FitH 757 ] /Parent 69 1 R /Prev 40 1 R >> endobj 53 1 obj << /Type /ExtGState /SA false /OP false /HT /Default >> endobj 55 1 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F5 121 0 R /F7 127 0 R /F9 128 0 R /F11 129 0 R >> /ExtGState << /GS1 53 1 R >> >> endobj 56 1 obj << /S /GoTo /D [ 124 0 R /FitH 847 ] >> endobj 58 1 obj << /Length 6818 >> stream
+1 1 1 rg
+BX /GS1 gs EX
+0 0.08 594.96 841.92 re
+f
+BT
+/F5 1 Tf
+12 0 0 12 517.68 38.24 Tm
+0 0 0 rg
+0 Tc
+0 Tw
+(2)Tj
+/F11 1 Tf
+10.08 0 0 10.08 111.36 748.158 Tm
+(A)Tj
+7.92 0 0 7.92 118.56 747.952 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 748.158 Tm
+0 Tc
+(T)Tj
+7.92 0 0 7.92 160.32 747.952 Tm
+0.003 Tc
+[(HRE)-22(E)]TJ
+10.08 0 0 10.08 181.2 748.158 Tm
+0.008 Tc
+0.004 Tw
+(: T)Tj
+7.92 0 0 7.92 192.96 747.952 Tm
+0.005 Tc
+[(HE)10( )]TJ
+10.08 0 0 10.08 205.44 748.158 Tm
+0 Tc
+0 Tw
+(T)Tj
+7.92 0 0 7.92 211.68 747.952 Tm
+[(IEBOU)25(T)-25( )]TJ
+10.08 0 0 10.08 242.64 748.158 Tm
+(M)Tj
+7.92 0 0 7.92 251.52 747.952 Tm
+0.005 Tc
+-0.013 Tw
+[(ODE)-20(L)10( O)-31(F)15( )]TJ
+10.08 0 0 10.08 287.04 748.158 Tm
+0 Tc
+0 Tw
+(M)Tj
+7.92 0 0 7.92 295.92 747.952 Tm
+0.003 Tc
+0.02 Tw
+[(OBI)-28(L)8(IT)-22(Y A)28(ND )]TJ
+10.08 0 0 10.08 349.2 748.158 Tm
+0 Tc
+0 Tw
+(P)Tj
+7.92 0 0 7.92 354.72 747.952 Tm
+0.03 Tc
+[(RE)35(F)10(E)35(R)30(E)35(N)-6(C)30(E)35( )]TJ
+10.08 0 0 10.08 402.48 748.158 Tm
+0 Tc
+(R)Tj
+7.92 0 0 7.92 408.96 747.952 Tm
+-0.001 Tc
+[(E)-57(V)-6(EL)-26(A)24(T)-26(ION)]TJ
+10.08 0 0 10.08 456.72 748.158 Tm
+0.012 Tc
+[(.....................)-237(5)12(8)]TJ
+/F9 1 Tf
+-33.0714 -1.1429 TD
+0 Tc
+0.012 Tw
+[(Mobi)-8(l)16(i)-8(t)16(y)-8( )24(i)-8(n)24( Ne)-8(w)48( Z)8(e)-8(al)-8(an)24(d)]TJ
+10.0238 0 TD
+0.012 Tc
+[(.............................................................................................................)-237(5)12(9)]TJ
+-10.0238 -1.1429 TD
+0.001 Tw
+[(P)27(r)19(o)11(b)11(lem)19(s)19( w)59(ith)11( M)11(o)11(b)35(il)27(it)27(y a)11(n)35(d)11( )24(Ef)27(fi)27(ci)27(en)11(c)26(y)-185(........................................................................................)-238(6)11(0)]TJ
+/F11 1 Tf
+-1.1905 -1.7381 TD
+0 Tc
+0 Tw
+(A)Tj
+7.92 0 0 7.92 118.56 707.392 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 707.598 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 159.6 707.392 Tm
+0.036 Tc
+[(OU)31(R)]TJ
+10.08 0 0 10.08 176.64 707.598 Tm
+0.008 Tc
+0.004 Tw
+(: O)Tj
+7.92 0 0 7.92 189.36 707.392 Tm
+0.025 Tc
+[(TH)20(E)30(R)25( )]TJ
+10.08 0 0 10.08 212.16 707.598 Tm
+0 Tc
+0 Tw
+(E)Tj
+7.92 0 0 7.92 218.4 707.392 Tm
+-0.003 Tc
+[(X)22(T)-28(ERN)-39(A)22(LIT)-28(I)-3(E)-28(S)]TJ
+10.08 0 0 10.08 277.2 707.598 Tm
+0.012 Tc
+[(.........................................................................................)-237(6)12(2)]TJ
+/F9 1 Tf
+-15.2619 -1.1429 TD
+-0.024 Tw
+[(T)20(a)12(x ex)27(ter)20(n)12(a)36(lit)28(ies)-193(..............................................................................................................)]TJ
+35.6911 0 TD
+[(...........)-237(6)12(2)]TJ
+-35.6911 -1.1429 TD
+[(ln)11(t)27(e)3(r)19(j)3(u)11(r)19(is)19(d)35(ict)27(io)11(n)11(a)35(l C)11(o)11(m)19(p)11(e)26(ti)27(tio)11(n)-225(................................................................................................)]TJ
+37.7857 0 TD
+[(...)-238(6)12(3)]TJ
+-37.7857 -1.1429 TD
+[(\223)20(N)12(o)12(t)4( in)12( )-24(m)43(y)4( b)12(a)12(c)27(kya)12(r)20(d)12(\224)44( )-24( N)12(I)12(M)35(BY)22(....................................................................................................)]TJ
+38.8095 0 TD
+0 Tc
+(64)Tj
+/F11 1 Tf
+-40 -1.7381 TD
+0 Tw
+(A)Tj
+7.92 0 0 7.92 118.56 655.312 Tm
+0.005 Tc
+[(P)15(P)-15(E)10(NDI)-26(X)30( )]TJ
+10.08 0 0 10.08 154.08 655.518 Tm
+0 Tc
+(F)Tj
+7.92 0 0 7.92 159.6 655.312 Tm
+0.031 Tc
+[(IV)26(E)]TJ
+10.08 0 0 10.08 173.04 655.518 Tm
+0.008 Tc
+0.004 Tw
+(: E)Tj
+7.92 0 0 7.92 184.8 655.312 Tm
+0.003 Tc
+-0.011 Tw
+[(QU)28(IT)-22(A)28(B)-27(L)8(E)8( )-31(S)13(H)-33(A)28(RING)-33( OF)-17( COS)13(T)-22(S)-17( )-31(A)28(ND B)-27(E)8(NE)-22(F)13(I)3(T)-22(S)]TJ
+10.08 0 0 10.08 361.68 655.518 Tm
+0.012 Tc
+[(.........................................................)-237(6)12(5)]TJ
+/F7 1 Tf
+-26.0238 -1.7621 TD
+[(R)20(E)12(F)28(E)12(R)20(E)12(N)20(C)20(E)12(S)-217(.....................................................................................................................)]TJ
+37.5485 0 TD
+[(.............)-238(6)12(7)]TJ
+/F3 1 Tf
+12 0 0 12 99.36 590.48 Tm
+0.008 Tc
+-0.026 Tw
+[(Tabl)6(e)24( )-20(of Fi)6(g)19(u)-1(r)17(e)4(s)]TJ
+/F9 1 Tf
+10.08 0 0 10.08 99.36 564.798 Tm
+0.012 Tc
+0 Tw
+[(F)28(i)4(g)12(u)12(r)20(e 1)36( )24( D)20(e)4(v)27(o)12(lu)36(tio)12(n)36( F)28(r)20(a)12(m)20(ew)60(o)12(r)20(k)-232(.................................................................................................)]TJ
+38.8572 0 TD
+[(..........)-214(6)]TJ
+-38.8572 -1.7381 TD
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 2)35( )24( S)11(i)3(n)11(g)35(le)26( a)11(n)35(d)11( D)19(o)11(u)35(b)11(le)26( P)27(e)3(a)35(ked)35( P)27(r)19(ef)27(er)19(en)35(ce)26( D)19(e)3(n)11(s)43(it)27(y F)27(u)11(n)11(c)26(ti)27(o)11(n)11(s)-191(......................................................)-238(1)11(5)]TJ
+T*
+[(F)27(i)3(g)11(u)11(r)19(e 3)11(:)34( D)42(evo)35(lu)11(t)27(i)3(o)11(n)35( a)11(n)11(d)35( P)27(o)11(li)27(ti)27(ca)11(l)27( D)19(e)26(cis)19(i)27(o)11(n)11( )24(M)11(a)11(k)26(in)11(g)-128(............................................................................)-239(2)]TJ
+41.6906 0 TD
+0 Tc
+0 Tw
+(5)Tj
+-41.6906 -1.7381 TD
+0.011 Tc
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 4)11(:)34( D)42(evo)35(lu)11(t)27(i)3(o)11(n)35( a)11(n)11(d)35( E)27(ffi)27(ci)27(en)35(t P)27(r)19(o)11(v)26(is)19(io)11(n)14(...................................................................................)]TJ
+39.6437 0 TD
+[(.....)-237(3)12(4)]TJ
+-39.6437 -1.7381 TD
+0 Tc
+0.012 Tw
+[(F)16(i)-8(gur)8(e)-8( 5)24( )24( D)8(e)-8(v)15(o)0(l)-8(u)24(t)-8(i)-8(o)0(n)24( an)24(d P)16(ubl)16(i)-8(c)15( G)8(oods)]TJ
+15.8095 0 TD
+0.012 Tc
+[(................................................................................................)-237(3)12(9)]TJ
+-15.8095 -1.7381 TD
+0.001 Tw
+[(F)27(i)3(g)11(u)11(r)19(e 6)35( O)19(v)26(er)19(-)11(p)11(r)19(o)11(d)11(u)35(ct)27(io)11(n)35( o)11(f)27( e)26(x)3(t)27(e)3(r)19(n)11(a)11(l)27(it)27(ies)-26(......................................................................................)]TJ
+39.12 0 TD
+[(.......)-237(5)12(2)]TJ
+-39.12 -1.7381 TD
+0 Tc
+0.012 Tw
+[(F)16(i)-8(gur)8(e)-8( 7)24( )24( U)8(nde)-8(r)8(-pr)8(o)24(v)-8(i)-8(s)8(i)16(on )24(of)16( P)16(ubl)-8(i)16(c)-8( G)31(oods)]TJ
+17.3809 0 TD
+0.012 Tc
+[(..........................................................................................)-237(5)12(3)]TJ
+-17.3809 -1.7381 TD
+0 Tc
+[(F)16(i)-8(gur)8(e)-8( 8)24( )24( E)16(c)-8(onom)8(i)16(e)-8(s)8( )24(and D)31(i)-8(s)8(e)15(c)-8(onom)8(i)16(e)-8(s)8( o)24(f)-8( )24(Sc)-8(a)24(l)-8(e)15( i)-8(n)24( Com)8(m)8(u)24(ni)-8(t)16(y)15( Si)-8(z)8(e)]TJ
+27.0714 0 TD
+0.012 Tc
+[(.....................................................)-237(6)12(2)]TJ
+ET
+endstream endobj 60 1 obj << /Type /Page /Parent 123 0 R /Resources 55 1 R /Contents 58 1 R >> endobj 64 1 obj << /Title (Sovereignty issues) /Dest [ null /FitH 740 ] /Parent 81 1 R /First 75 1 R /Last 75 1 R /Count 2 >> endobj 65 1 obj << /Title (Advantages of separating political and implementation roles: the regulat\ or / provider split) /Dest [ null /FitH 325 ] /Parent 72 1 R /Prev 66 1 R /Next 70 1 R >> endobj 66 1 obj << /Title (Solutions to contracting problems) /Dest [ null /FitH 477 ] /Parent 72 1 R /Prev 68 1 R /Next 65 1 R /First 67 1 R /Last 67 1 R /Count 1 >> endobj 67 1 obj << /Title (Informal / Non-financial contracts) /Dest [ null /FitH 576 ] /Parent 66 1 R >> endobj 68 1 obj << /Title (Contracting problems) /Dest [ null /FitH 325 ] /Parent 72 1 R /Next 66 1 R >> endobj 69 1 obj << /Title (4\tIMPLEMENTATION) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 17 1 R /Next 72 1 R /First 48 1 R /Last 51 1 R /Count 11 >> endobj 70 1 obj << /Title (The Framework: The Whole Picture) /Dest [ null /FitH 712 ] /Parent 72 1 R /Prev 65 1 R >> endobj 72 1 obj << /Title (5\tCAN WE SEPARATE DECISION MAKING FROM IMPLEMENTATION?) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 69 1 R /Next 81 1 R /First 68 1 R /Last 70 1 R /Count 5 >> endobj 74 1 obj << /Title (7 Conclusions and recommendations) /Dest [ null /FitH 506 ] /Parent 75 1 R >> endobj 75 1 obj << /Title () /Dest [ null /FitH 506 ] /Parent 64 1 R /First 74 1 R /Last 74 1 R /Count 1 >> endobj 77 1 obj << /ProcSet [ /PDF /Text ] /Font << /F3 120 0 R /F7 127 0 R /F9 128 0 R /F11 129 0 R >> /ExtGState << /GS1 53 1 R >> >> endobj 80 1 obj << /Title (Role of Central Government) /Dest [ null /FitH 702 ] /Parent 88 1 R /Prev 86 1 R /Next 95 1 R >> endobj 81 1 obj << /Title (6\tACCOUNTABILITY OF GOVERNMENT) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 72 1 R /Next 86 1 R /First 64 1 R /Last 64 1 R /Count 3 >> endobj 83 1 obj << /Title (Appendix One: The Resource Management Act 1991) /Dest [ null /FitH 711 ] /Parent 86 1 R /First 85 1 R /Last 85 1 R /Count 1 >> endobj 85 1 obj << /Title (Major Aspects of the RMA) /Dest [ null /FitH 163 ] /Parent 83 1 R >> endobj 86 1 obj << /Title (APPENDICES) /Dest [ null /FitH 740 ] /Parent 88 1 R /Prev 81 1 R /Next 80 1 R /First 83 1 R /Last 83 1 R /Count 2 >> endobj 88 1 obj << /Count 73 /First 335 0 R /Last 104 1 R /Parent 305 0 R /Prev 117 0 R /Dest [ null 0 0 1 ] /Title (98-7x.pdf) >> endobj 92 1 obj << /Title () /Dest [ null /FitH 411 ] /Parent 88 1 R /Prev 93 1 R /Next 99 1 R >> endobj 93 1 obj << /Title (Appendix Three: The Tiebout Model of Mobility and Preference Revelation) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 94 1 R /Next 92 1 R >> endobj 94 1 obj << /Title (Appendix Two: Why and what should we regulate?) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 95 1 R /Next 93 1 R >> endobj 95 1 obj << /Title (Roles of Local Authorities) /Dest [ null /FitH 522 ] /Parent 88 1 R /Prev 80 1 R /Next 94 1 R >> endobj 99 1 obj << /Title (Effects of Financing Public Good Provision on Efficient Migration Patter\ ns) /Dest [ null /FitH 411 ] /Parent 88 1 R /Prev 92 1 R /Next 101 1 R >> endobj 101 1 obj << /Title (Appendix Four: Other Externalities) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 99 1 R /Next 102 1 R >> endobj 102 1 obj << /Title (Appendix Five: Equitable sharing of costs and benefits) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 101 1 R /Next 104 1 R >> endobj 104 1 obj << /Title (REFERENCES) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 102 1 R >> endobj 117 0 obj << /Title (REFERENCES) /Dest [ 116 0 R /FitH 757 ] /Parent 305 0 R /Prev 97 0 R /Next 88 1 R >> endobj 123 0 obj << /Type /Pages /Kids [ 1 0 R 35 1 R 60 1 R 4 0 R 7 0 R ] /Count 5 /Parent 151 0 R >> endobj 130 1 obj << /S /GoTo /D [ 35 1 R /FitH 786 ] >> endobj 139 0 obj << /Type /Page /Parent 37 1 R /Resources 141 0 R /Contents 140 0 R >> endobj 151 0 obj << /Type /Pages /Kids [ 123 0 R 37 1 R 152 0 R 176 0 R 200 0 R 224 0 R 250 0 R 278 0 R ] /Count 70 /MediaBox [ 0 0 595 842 ] >> endobj 305 0 obj << /Count 91 /First 3 0 R /Last 88 1 R >> endobj 307 0 obj << /CreationDate (D:19981120125044) /Producer (\376\377\000A\000c\000r\000o\000b\000a\000t\000 \000D\000i\000s\000t\000\ i\000l\000l\000e\000r\000 \0003\000.\0000\0001\000 \000f\000o\000r\000 \000\ W\000i\000n\000d\000o\000w\000s) /Creator (PSCRIPT.DRV Version 4.0) /Title (Microsoft Word - Tsy WP 98-7.doc) /ModDate (D:19981120140533) >> endobj 308 0 obj << /Title (Pecuniary externalities) /Dest [ null /FitH 452 ] /Parent 2 1 R /Prev 309 0 R >> endobj 309 0 obj << /Title (Network extemalities) /Dest [ null /FitH 660 ] /Parent 2 1 R /Prev 310 0 R /Next 308 0 R >> endobj 310 0 obj << /Title (Environmental externalities) /Dest [ null /FitH 261 ] /Parent 2 1 R /Next 309 0 R >> endobj 311 0 obj << /Title (Between Jurisdictions: Interjurisdictional Externalities) /Dest [ null /FitH 451 ] /Parent 9 1 R /Prev 312 0 R /Next 8 1 R >> endobj 312 0 obj << /Title (Within Jurisdictions) /Dest [ null /FitH 714 ] /Parent 9 1 R /Next 311 0 R >> endobj 313 0 obj << /Title (Informed decision making) /Dest [ null /FitH 394 ] /Parent 11 1 R /Next 9 1 R >> endobj 314 0 obj << /Title (Social Choice Mechanisms) /Dest [ null /FitH 392 ] /Parent 6 1 R /Prev 315 0 R /Next 11 1 R >> endobj 315 0 obj << /Title (The Problem with Public Goods: Preference Revelation) /Dest [ null /FitH 615 ] /Parent 6 1 R /Next 314 0 R >> endobj 316 0 obj << /Title (2\tWHY AND WHAT SHOULD WE REGULATE?) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 319 0 R /Next 6 1 R /First 318 0 R /Last 317 0 R /Count 2 >> endobj 317 0 obj << /Title (Information failures) /Dest [ null /FitH 546 ] /Parent 316 0 R /Prev 318 0 R >> endobj 318 0 obj << /Title (Externalities and Public Goods) /Dest [ null /FitH 574 ] /Parent 316 0 R /Next 317 0 R >> endobj 319 0 obj << /Title (1\tINTRODUCTION) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 323 0 R /Next 316 0 R /First 322 0 R /Last 320 0 R /Count 3 >> endobj 320 0 obj << /Title (Aims and structure of this paper) /Dest [ null /FitH 712 ] /Parent 319 0 R /Prev 321 0 R >> endobj 321 0 obj << /Title (The Resource Management Act) /Dest [ null /FitH 712 ] /Parent 319 0 R /Prev 322 0 R /Next 320 0 R >> endobj 322 0 obj << /Title (Devolution and decentralisation) /Dest [ null /FitH 728 ] /Parent 319 0 R /Next 321 0 R >> endobj 323 0 obj << /Title (EXECUTIVE SUMMARY) /Dest [ null /FitH 757 ] /Parent 88 1 R /Prev 334 0 R /Next 319 0 R /First 329 0 R /Last 324 0 R /Count 10 >> endobj 324 0 obj << /Title (Framework for Analysis of Devolution) /Dest [ null /FitH 291 ] /Parent 323 0 R /Prev 325 0 R >> endobj 325 0 obj << /Title (Sovereignty) /Dest [ null /FitH 390 ] /Parent 323 0 R /Prev 326 0 R /Next 324 0 R >> endobj 326 0 obj << /Title (Accountability of Government) /Dest [ null /FitH 516 ] /Parent 323 0 R /Prev 327 0 R /Next 325 0 R >> endobj 327 0 obj << /Title (Separability of Implementation from Decision-Making?) /Dest [ null /FitH 657 ] /Parent 323 0 R /Prev 328 0 R /Next 326 0 R >> endobj 328 0 obj << /Title (Implementation) /Dest [ null /FitH 204 ] /Parent 323 0 R /Prev 329 0 R /Next 327 0 R >> endobj 329 0 obj << /Title (Social Decision Making and Cost Bearing) /Dest [ null /FitH 173 ] /Parent 323 0 R /Next 328 0 R /First 330 0 R /Last 330 0 R /Count 4 >> endobj 330 0 obj << /Title () /Dest [ null /FitH 632 ] /Parent 329 0 R /First 333 0 R /Last 331 0 R /Count 3 >> endobj 331 0 obj << /Title (3\tCost effective decision making) /Dest [ null /FitH 414 ] /Parent 330 0 R /Prev 332 0 R >> endobj 332 0 obj << /Title (2\tBalanced decision making.) /Dest [ null /FitH 523 ] /Parent 330 0 R /Prev 333 0 R /Next 331 0 R >> endobj 333 0 obj << /Title (1\tInformed decision-making.) /Dest [ null /FitH 632 ] /Parent 330 0 R /Next 332 0 R >> endobj 334 0 obj << /Title (ABSTRACT) /Dest [ null /FitH 468 ] /Parent 88 1 R /Prev 335 0 R /Next 323 0 R >> endobj 335 0 obj << /Title (Suzi Kerr, Megan Claridge & Dominic Milicich*) /Dest [ null /FitH 573 ] /Parent 88 1 R /Next 334 0 R >> endobj xref 0 1 0000000124 65535 f
+2 2 0000584481 00001 n
+0000584596 00000 n
+5 2 0000584695 00000 n
+0000584827 00001 n
+8 11 0000585024 00001 n
+0000585194 00001 n
+0000585361 00001 n
+0000585480 00001 n
+0000585654 00001 n
+0000585801 00000 n
+0000585893 00001 n
+0000586050 00001 n
+0000586197 00001 n
+0000586310 00001 n
+0000586463 00000 n
+20 1 0000586555 00001 n
+22 1 0000586641 00000 n
+24 1 0000586733 00000 n
+28 1 0000586825 00001 n
+30 1 0000586922 00001 n
+33 1 0000586980 00001 n
+35 1 0000602778 00001 n
+37 2 0000602869 00001 n
+0000602981 00001 n
+40 1 0000603096 00001 n
+42 5 0000603210 00001 n
+0000603325 00001 n
+0000603440 00001 n
+0000603555 00001 n
+0000603689 00001 n
+48 2 0000603804 00001 n
+0000603933 00001 n
+51 1 0000604071 00001 n
+53 1 0000604200 00001 n
+55 2 0000604278 00001 n
+0000604431 00001 n
+58 1 0000604491 00001 n
+60 1 0000611363 00001 n
+64 7 0000611454 00001 n
+0000611587 00001 n
+0000611784 00001 n
+0000611960 00001 n
+0000612070 00001 n
+0000612180 00001 n
+0000612341 00001 n
+72 1 0000612463 00001 n
+74 2 0000612661 00001 n
+0000612771 00001 n
+77 1 0000612886 00001 n
+80 2 0000613027 00001 n
+0000613157 00001 n
+83 1 0000613331 00001 n
+85 2 0000613492 00001 n
+0000613592 00001 n
+88 1 0000613745 00001 n
+92 4 0000613884 00001 n
+0000613988 00001 n
+0000614163 00001 n
+0000614313 00001 n
+99 1 0000614443 00001 n
+101 2 0000614624 00001 n
+0000614764 00001 n
+104 1 0000614925 00001 n
+117 1 0000615027 00000 n
+123 2 0000615147 00000 n
+0000000000 00001 f
+130 1 0000615256 00001 n
+139 1 0000615316 00000 n
+151 1 0000615409 00000 n
+305 1 0000615560 00000 n
+307 29 0000615624 00000 n
+0000615982 00000 n
+0000616096 00000 n
+0000616222 00000 n
+0000616340 00000 n
+0000616500 00000 n
+0000616611 00000 n
+0000616725 00000 n
+0000616854 00000 n
+0000616997 00000 n
+0000617178 00000 n
+0000617291 00000 n
+0000617414 00000 n
+0000617577 00000 n
+0000617702 00000 n
+0000617837 00000 n
+0000617961 00000 n
+0000618127 00000 n
+0000618256 00000 n
+0000618375 00000 n
+0000618511 00000 n
+0000618671 00000 n
+0000618793 00000 n
+0000618966 00000 n
+0000619085 00000 n
+0000619211 00000 n
+0000619347 00000 n
+0000619468 00000 n
+0000619583 00000 n
+trailer << /Size 336 /Info 307 0 R /Root 306 0 R /Prev 578158 /ID[<7ddd760ba1955f40826faf1aa6a273d8><aa695c3ff54fdbd3a6d65f6c1c9df52d>] >> startxref 619720 %%EOF 117 0 obj << /Title (REFERENCES) /Dest [ 116 0 R /FitH 757 ] /Parent 305 0 R /Prev 97 0 R >> endobj 305 0 obj << /Count 17 /First 3 0 R /Last 117 0 R >> endobj 307 0 obj << /CreationDate (D:19981120125044) /Producer (\376\377\000A\000c\000r\000o\000b\000a\000t\000 \000D\000i\000s\000t\000\ i\000l\000l\000e\000r\000 \0003\000.\0000\0001\000 \000f\000o\000r\000 \000\ W\000i\000n\000d\000o\000w\000s) /Creator (PSCRIPT.DRV Version 4.0) /Title (Microsoft Word - Tsy WP 98-7.doc) /ModDate (D:19981120140608) >> endobj xref 0 1 0000000088 65535 f
+2 1 0000000308 00002 f
+6 1 0000000011 00002 f
+8 5 0000000002 00002 f
+0000000008 00002 f
+0000000009 00002 f
+0000000010 00002 f
+0000000006 00002 f
+14 4 0000000012 00002 f
+0000000014 00002 f
+0000000015 00002 f
+0000000016 00002 f
+20 1 0000000017 00002 f
+38 1 0000000020 00002 f
+40 1 0000000044 00002 f
+42 5 0000000038 00002 f
+0000000042 00002 f
+0000000045 00002 f
+0000000049 00002 f
+0000000043 00002 f
+48 2 0000000046 00002 f
+0000000048 00002 f
+51 1 0000000040 00002 f
+64 7 0000000075 00002 f
+0000000066 00002 f
+0000000067 00002 f
+0000000068 00002 f
+0000000069 00002 f
+0000000051 00002 f
+0000000065 00002 f
+72 1 0000000070 00002 f
+74 2 0000000072 00002 f
+0000000074 00002 f
+80 2 0000000086 00002 f
+0000000064 00002 f
+83 1 0000000085 00002 f
+85 2 0000000081 00002 f
+0000000083 00002 f
+88 1 0000000104 00002 f
+92 4 0000000093 00002 f
+0000000094 00002 f
+0000000095 00002 f
+0000000080 00002 f
+99 1 0000000092 00002 f
+101 2 0000000099 00002 f
+0000000101 00002 f
+104 1 0000000102 00002 f
+117 1 0000622131 00000 n
+305 1 0000622237 00000 n
+307 29 0000622302 00000 n
+0000000309 00001 f
+0000000310 00001 f
+0000000311 00001 f
+0000000312 00001 f
+0000000313 00001 f
+0000000314 00001 f
+0000000315 00001 f
+0000000316 00001 f
+0000000317 00001 f
+0000000318 00001 f
+0000000319 00001 f
+0000000320 00001 f
+0000000321 00001 f
+0000000322 00001 f
+0000000323 00001 f
+0000000324 00001 f
+0000000325 00001 f
+0000000326 00001 f
+0000000327 00001 f
+0000000328 00001 f
+0000000329 00001 f
+0000000330 00001 f
+0000000331 00001 f
+0000000332 00001 f
+0000000333 00001 f
+0000000334 00001 f
+0000000335 00001 f
+0000000124 00001 f
+trailer << /Size 336 /Info 307 0 R /Root 306 0 R /Prev 619720 /ID[<7ddd760ba1955f40826faf1aa6a273d8><7aeef9c8bbc72ea88f7ad77960764ad1>] >> startxref 622660 %%EOF 307 0 obj << /CreationDate (D:19981120125044) /Producer (\376\377\000A\000c\000r\000o\000b\000a\000t\000 \000D\000i\000s\000t\000\ i\000l\000l\000e\000r\000 \0003\000.\0000\0001\000 \000f\000o\000r\000 \000\ W\000i\000n\000d\000o\000w\000s) /Creator (PSCRIPT.DRV Version 4.0) /Title (PDF File - Devolution & the New Zealand Resource Management Act - Workin\ g Papers - The Treasury) /ModDate (D:20000911121701) /Author (New Zealand Treasury) >> endobj xref 307 1 0000624542 00000 n
+trailer << /Size 336 /Info 307 0 R /Root 306 0 R /Prev 622660 /ID[<7ddd760ba1955f40826faf1aa6a273d8><1f8017d6d2daa698938b187a1c40bea6>] >> startxref 624996 %%EOF \ No newline at end of file
diff --git a/assignment1/materials/eia-international-law.pdf b/assignment1/materials/eia-international-law.pdf
new file mode 100644
index 0000000..765281d
--- /dev/null
+++ b/assignment1/materials/eia-international-law.pdf
Binary files differ
diff --git a/assignment1/materials/eia-retrospect-prospect.pdf b/assignment1/materials/eia-retrospect-prospect.pdf
new file mode 100644
index 0000000..b4b3cfb
--- /dev/null
+++ b/assignment1/materials/eia-retrospect-prospect.pdf
Binary files differ
diff --git a/assignment1/materials/impact-significance.pdf b/assignment1/materials/impact-significance.pdf
new file mode 100644
index 0000000..a666bdf
--- /dev/null
+++ b/assignment1/materials/impact-significance.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/26.pdf b/assignment1/materials/implementing-sustainability/26.pdf
new file mode 100644
index 0000000..7342f90
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/26.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/27.pdf b/assignment1/materials/implementing-sustainability/27.pdf
new file mode 100644
index 0000000..2e64dc5
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/27.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/28.pdf b/assignment1/materials/implementing-sustainability/28.pdf
new file mode 100644
index 0000000..4bb9df1
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/28.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/29.pdf b/assignment1/materials/implementing-sustainability/29.pdf
new file mode 100644
index 0000000..10c57c7
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/29.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/30.pdf b/assignment1/materials/implementing-sustainability/30.pdf
new file mode 100644
index 0000000..2d183ff
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/30.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/31.pdf b/assignment1/materials/implementing-sustainability/31.pdf
new file mode 100644
index 0000000..da6c84c
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/31.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/32.pdf b/assignment1/materials/implementing-sustainability/32.pdf
new file mode 100644
index 0000000..7a89d65
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/32.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/33.pdf b/assignment1/materials/implementing-sustainability/33.pdf
new file mode 100644
index 0000000..23e537f
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/33.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/39.pdf b/assignment1/materials/implementing-sustainability/39.pdf
new file mode 100644
index 0000000..e19f83f
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/39.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/40.pdf b/assignment1/materials/implementing-sustainability/40.pdf
new file mode 100644
index 0000000..f911017
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/40.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/46.pdf b/assignment1/materials/implementing-sustainability/46.pdf
new file mode 100644
index 0000000..9620e22
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/46.pdf
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/GetPage(5).aspx b/assignment1/materials/implementing-sustainability/GetPage(5).aspx
new file mode 100644
index 0000000..544b37e
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/GetPage(5).aspx
Binary files differ
diff --git a/assignment1/materials/implementing-sustainability/test.pdf b/assignment1/materials/implementing-sustainability/test.pdf
new file mode 100644
index 0000000..5310747
--- /dev/null
+++ b/assignment1/materials/implementing-sustainability/test.pdf
Binary files differ
diff --git a/assignment1/materials/institutional-framework-for-sustainability.pdf b/assignment1/materials/institutional-framework-for-sustainability.pdf
new file mode 100644
index 0000000..af0f991
--- /dev/null
+++ b/assignment1/materials/institutional-framework-for-sustainability.pdf
Binary files differ
diff --git a/assignment1/materials/nz-eia-simultaneous-preparation-and-review.pdf b/assignment1/materials/nz-eia-simultaneous-preparation-and-review.pdf
new file mode 100644
index 0000000..cc3eddb
--- /dev/null
+++ b/assignment1/materials/nz-eia-simultaneous-preparation-and-review.pdf
Binary files differ
diff --git a/assignment1/materials/practitioners.pdf b/assignment1/materials/practitioners.pdf
new file mode 100644
index 0000000..d5db685
--- /dev/null
+++ b/assignment1/materials/practitioners.pdf
Binary files differ
diff --git a/assignment1/materials/precautionary-principle-EIA.pdf b/assignment1/materials/precautionary-principle-EIA.pdf
new file mode 100644
index 0000000..1c334ce
--- /dev/null
+++ b/assignment1/materials/precautionary-principle-EIA.pdf
Binary files differ
diff --git a/assignment1/materials/state-of-the-art-of-EIA.pdf b/assignment1/materials/state-of-the-art-of-EIA.pdf
new file mode 100644
index 0000000..147cc99
--- /dev/null
+++ b/assignment1/materials/state-of-the-art-of-EIA.pdf
Binary files differ
diff --git a/assignment1/materials/state-of-the-art-of-policy-assessment.pdf b/assignment1/materials/state-of-the-art-of-policy-assessment.pdf
new file mode 100644
index 0000000..059a5c1
--- /dev/null
+++ b/assignment1/materials/state-of-the-art-of-policy-assessment.pdf
Binary files differ
diff --git a/assignment1/materials/state-of-the-art-sustainability-assessment.pdf b/assignment1/materials/state-of-the-art-sustainability-assessment.pdf
new file mode 100644
index 0000000..c572d62
--- /dev/null
+++ b/assignment1/materials/state-of-the-art-sustainability-assessment.pdf
Binary files differ